遞迴的實際業務場景之MySQL 遞迴查詢
喜歡就點個讚唄!
原始碼<--請點選此處檢視
引入
當我看到一些評論時,例如下面的樣子。我挺好奇這個功能是怎麼樣做出來的。進過查閱資料,發現這其實是 MySQL 的遞迴操作。下面就讓我操作一下怎麼實現 MySQL 的遞迴查詢。
設計資料庫
觀察這種資料庫設計,你會發現他都有一個父節點,一直到根節點,所以我們設計資料庫的時候,應該設定一個 parentid 欄位。所以,我們可以得到以下的資料庫。
sql 指令碼如下
CREATE TABLE digui( id INT(11) NOT null auto_increment, msg VARCHAR(255) not NULL COMMENT '評論的內容', parentid int(11) not null COMMENT '上一條', PRIMARY KEY(id) )ENGINE=INNODB auto_increment = 100 DEFAULT CHARSET=utf8mb4; INSERT into `digui`(msg, parentid) VALUES ('A', 0); INSERT into `digui`(msg, parentid) VALUES('B', 1); INSERT into `digui`(msg, parentid) VALUES('D', 3); INSERT into `digui`(msg, parentid) VALUES('C', 2);
其實實現 MySQL 的遞迴查詢方法有很多
- 使用 MySQL 儲存過程
- 應用層程式碼遞迴
- MyBatis 的 collection 標籤
方案1 應用層程式碼遞迴
//應用層遞迴查詢 @Override public List<Digui> getAll(int parent) { List<Digui> deptVosList=new ArrayList<>(); QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("parentid", parent); List<Digui> list1 = list(queryWrapper); for (Digui digui: list1) { Digui digui1 = new Digui(); digui1.setId(digui.getId()); digui1.setMsg(digui.getMsg()); digui1.setParentid(digui.getParentid()); // 此處遞迴呼叫賦值 digui1.setDiguiList(getAll(digui.getId())); deptVosList.add(digui1); } return deptVosList; }
方案2 MyBatis 的 collection 標籤
<resultMap id="RecursiveMap" type="com.example.lsbdigui.entity.Digui"> <result property="id" column="id"/> <result property="msg" column="msg"/> <result property="parentid" column="parentid"/> <collection property="diguiList" ofType="com.example.lsbdigui.entity.Digui" select="com.example.lsbdigui.mapper.DiguiMapper.getAllBySQL" column="id"/> </resultMap> <select id="getAllBySQL" resultMap="RecursiveMap"> select * from digui where parentid = #{parent} </select>
使用<collection>
、<select>
標籤實現 sql 遞迴查詢。
結果
{
"code": 200,
"msg": "正確返回",
"date": [
{
"id": 100,
"msg": "A",
"parentid": 0,
"diguiList": [
{
"id": 101,
"msg": "B",
"parentid": 100,
"diguiList": [
{
"id": 103,
"msg": "C",
"parentid": 101,
"diguiList": [
{
"id": 102,
"msg": "D",
"parentid": 103,
"diguiList": []
}
]
}
]
}
]
}
]
}
對比
建議
應用層可以一次查詢全部資料,然後再遞迴找出需要的資料,這樣可以減少資料庫查詢,效能更佳。
參考
- https://blog.rxliuli.com/p/5830226b/
- https://juejin.im/entry/59be34fe5188257e8b36a303
- https://blog.csdn.net/u014079773/article/details/53338116
關注微信公眾號,隨時移動端閱讀
相關推薦
遞迴的實際業務場景之MySQL 遞迴查詢
喜歡就點個讚唄! 原始碼<--請點選此處檢視 引入 當我看到一些評論時,例如下面的樣子。我挺好奇這個功能是怎麼樣做出來的。進過查閱資料,發現這其實是 MySQL 的遞迴操作。下面就讓我操作一下怎麼實現 MySQL 的遞迴查詢。 設計資料庫 觀察這種資料庫設計,你會發現他都有一個父節點,一直到根節
從React Redux的實際業務場景來看有限狀態機
寫在前面 上一篇:從Promise的實現來看有限狀態機 上一篇講到了一個簡單的,利用了有限狀態機的前端實現Promise。Promise的有限狀態機除了start以及finish兩個狀態,其核心的三個狀態其實就是一個非同步行為的三種狀態:PENDING、FULFILLED、REJECTED。通過非同步行為
通過實際業務場景理解後端介面的冪等性
寫在前面:之前在設計介面時因經驗尚淺,並未過多考慮冪等性,但這兩天出現的一個線上問題讓我認識到了某些情況下介面冪等性的重要性; 非冪等場景: 服務A將單據A資訊通過RPC遠端過程呼叫傳給下游服務B介
訊息中介軟體在企業系統中的實際業務場景分析
比如某系統有三個子系統,登入系統、積分系統群、日誌系統群。 一個使用者登入了系統,將傳送通知給積分系統叢集和日誌系統叢集,要求積分系統叢集和日誌系統叢集都能接收到完整的登入實現通知,類似於主題模式,同時在其中任一個系統群中不能讓一個訊息被叢集中的多個系統重複處理,這類似於佇
mysql數據庫從刪庫到跑路之mysql多表查詢
logs 插入 並且 所有 方式 color dep join 查看表 一 介紹 本節主題 多表連接查詢 復合條件連接查詢 子查詢 準備表 company.employeecompany.department #建表 create table department( id
面試題之MySQL多表查詢方法
一使用SELECT子句進行多表查詢 SELECT 欄位名 FROM 表1,表2 … WHERE 表1.欄位 = 表2.欄位 AND 其它查詢條件 SELECT a.id,a.name,a.address,a.date,b.math,b.english,b.chinese
基於遞迴演算法,樹形結構資料下業務場景,封裝解決方法
本文原始碼:GitHub·點這裡 || GitEE·點這裡 一、遞迴演算法 1、概念簡介 遞迴演算法的核心思想是通過將問題重複分解為同類的或其子問題的方式,從而可以使用統一的解決方式。很多程式語言支援方法或函式自我呼叫,簡單的說,就是在函式或方法體內,自身可以再次呼叫自身的方法結構。 2、基礎案例 這裡通過遞
順序表應用7:最大子段和之分治遞迴法(SDUT 3664)
#include <bits/stdc++.h> using namespace std; const int maxn = 50005; int num = 0; struct node { int *elem; int len; }; void Creatlist(
資料結構之DFS遞迴與非遞迴遍歷鄰接表存圖
學習鄰接表存圖請看:https://blog.csdn.net/HPU_FRDHR/article/details/83957240 DFS (深度優先搜尋) 深度優先搜尋演算法(英語:Depth-First-S
Python之初識遞迴
什麼是遞迴 在函式中呼叫函式本身,就是遞迴,當然不能無限制呼叫,呼叫深度為997,想要修改遞迴深度,用sys模組 import sys sys.setrecursionlimit(100000) # 修改深度為100000,具體到多少得看及計算機效能 斐波那契數列 # 函式形式的
mysql遞迴查詢,mysql中從子類ID查詢所有父類(做無限分類經常用到)
由於mysql 不支援類似 oracle with ...connect的 遞迴查詢語法之前一直以為類似的查詢要麼用儲存過程要麼只能用程式寫遞迴查詢.現在發現原來一條sql語句也是可以搞定的先來看資料表的結構如下:id name parent_id&n
每日一題之 非遞迴後序遍歷列印二叉樹所有路徑
描述 給一個二叉樹,列印其所有路徑 思路: 利用後序非遞迴遍歷,因為後序非遞迴遍歷的特性,對於每次訪問的節點,棧裡面存的元素都是當前節點的祖先,所以只要判斷當前節點是不是葉子節點,如果是葉子節點,那麼將棧中元素取出,和當前葉子節點組成一條路徑。 #include <
C++ primer plus書之--C++遞迴呼叫
遞迴的思路和java的思路一樣, 直接看demo: // 遞迴 #include <iostream> using namespace std; const int Len = 66; const int Divs = 6; // 函式原型, 由於是陣列, 所以傳遞的是陣列的首地址
Mysql遞迴獲取某個父節點下面的所有子節點和子節點上的所有父節點
在MySQL中自定義函式來實現遞迴獲取所有子節點,該方式的優點是可以減少java程式碼量,缺點是:1.不好維護;2.拼接的欄位太長的時候,自定義函式的返回值可能容量不夠,此時可以定義為text等大容量型別;3:show variables like 'group_concat_max_len'&nb
順序表應用7:最大子段和之分治遞迴法 SDUT
順序表應用7:最大子段和之分治遞迴法 Time Limit: 10 ms Memory Limit: 400 KiB Problem Description 給定n(1<=n<=50000)個整數(可能為負數)組成的序列a[1],a[2],a[3]
python之路--遞迴, 二分法
1, 遞迴 自己呼叫自己, 遞迴的入口(引數) 和 出口(return), 樹形結構的遍歷. def func(): print("我是遞迴") func()func() 樹形結構的遍歷 import os def func(luji
mysql 遞迴查詢所有的子節點
<select id="findDto" resultMap="EmployeeDtoMap" parameterType="e="java.lang.Integer" >" > select * from ( select a.*, *, b.name as as department_
3664-順序表應用7:最大子段和之分治遞迴法-C語言
#include <stdio.h> #include <stdlib.h> int count=0; //定義全域性變數用來記錄遞迴次數 typedef struct{ int data[50010]; int length; }Lis
資料結構(四)之非遞迴遍歷二叉樹
void Inoder(Bitree root)//二叉樹的中序遍歷非遞迴 { IniStack(&S);//初始化一個棧 p=root; while(!isEmpty(S)||p!=NULL) { if(p!=NULL)//如果當前結點不為空進棧 { pu
遞迴替換演算法之尾遞迴
遞迴在很多時候被視為洪水猛獸。它的名聲狼籍,好像永遠和低效聯絡在一起。 其實,對一些如樹的遞迴結構,遞迴演算法是又自然又好用。 如果看看一些用來代替遞迴的技術,(漢諾塔的迭代演算法不去說它,那是真正的演算法的革命,除了佩服沒啥好說的),一般來說只不過是自己模擬堆疊,編起來費勁,讀起來費勁,維護起來更費勁。