亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > SQL Server > 正文

SQL 雙親節點查找所有子節點的實現方法

2024-08-31 01:03:52
字體:
來源:轉載
供稿:網友
下面小編就為大家帶來一篇SQL 雙親節點查找所有子節點的實現方法。小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
 

怎么保存樹狀結構的數據呢?在 SQL 中常用的是雙親節點法。創建表如下 

CREATE TABLE category ( id LONG, parentId LONG, name String(20) )INSERT INTO category VALUES ( 1, NULL, 'Root' )INSERT INTO category VALUES ( 2, 1, 'Branch1' )INSERT INTO category VALUES ( 3, 1, 'Branch2' )INSERT INTO category VALUES ( 4, 3, 'SubBranch1' )INSERT INTO category VALUES ( 5, 2, 'SubBranch2' )

其中,parent id 表示父節點, name 是節點名稱。

假設當前欲獲取某一節點下所有子節點(獲取后代 Descendants),該怎么做呢?如果使用程序(Java/PHP)遞歸調用,那么將在數據庫與本地開發語言之間來回訪問,效率之低可想而知。于是我們希望在數據庫的層面就可以完成,——該怎么做呢?

遞歸法

經查詢,最好的方法(個人覺得)是 SQL 遞歸 CTE 的方法。所謂 CTE 是 Common Table Expressison 公用表表達式的意思。網友評價說:“CTE 是一種十分優雅的存在。CTE 所帶來最大的好處是代碼可讀性的提升,這是良好代碼的必須品質之一。使用遞歸 CTE 可以更加輕松愉快的用優雅簡潔的方式實現復雜的查詢。”——其實我對 SQL 不太熟悉,大家谷歌下其意思即可。

怎么用 CTE 呢?我們用小巧數據庫 SQLite,它就支持!別看他體積不大,卻也能支持最新 SQL99 的 with 語句,例子如下。 

WITH w1( id, parentId, name) AS (		SELECT 			category.id, 			category.parentId,             category.name		FROM 			category 		WHERE 			id = 1	UNION ALL 		SELECT 			category.id, 			category.parentId,             category.name		FROM 			category JOIN w1 ON category.parentId= w1.id) 

SELECT * FROM w1;其中 WHERE id = 1 是那個父節點之 id,你可以改為你的變量。簡單說,遞歸 CTE 最少包含兩個查詢(也被稱為成員)。第一個查詢為定點成員,定點成員只是一個返回有效表的查詢,用于遞歸的基礎或定位點。第二個查詢被稱為遞歸成員,使該查詢稱為遞歸成員的是對 CTE 名稱的遞歸引用是觸發。在邏輯上可以將 CTE 名稱的內部應用理解為前一個查詢的結果集。遞歸查詢沒有顯式的遞歸終止條件,只有當第二個遞歸查詢返回空結果集或是超出了遞歸次數的最大限制時才停止遞歸。遞歸次數上限的方法是使用 MAXRECURION。

SQL,雙親節點

 

相應地給出查找所有父節點的方法(獲取祖先 Ancestors,就是把 id 和 parentId 反過來)

WITH w1( id, parentId, name, level) AS  (    SELECT          id,          parentId,          name,        0 AS level      FROM          category        WHERE          id = 6     UNION ALL        SELECT          category.id,          category.parentId,          category.name ,        level + 1      FROM          category JOIN w1 ON category.id= w1.parentId )  SELECT * FROM w1; 

無奈的 MySQL

SQLite ok 了,而 MySQL 呢?

在另一邊廂,大家都愛用的 MySQL 卻無視 with 語句,官網博客上明確說明是壓根不支持,十分不方便,明明可以很簡單事情為什么不能用呢?——而且 MySQL 也好像沒有計劃在將來的新版本中添加 with 的 cte 功能。于是大家想出了很多辦法。其實不就是一個遞歸程序么——應該不難——寫函數或者存儲過程總該行吧?沒錯,的確如此,——寫遞歸不是問題,問題是用 SQL 寫就是個問題——還是那句話,“隔行如隔山”,雖然有點夸張的說法,但我想既懂數據庫又懂各種數據庫方言寫法(存儲過程)的人應該不是很多吧~,——不細究了,反正就是代碼帖來貼去唄~

我這里就不貼 SQL 了,可以看這里的,《MySQL中進行樹狀所有子節點的查詢》

至此,我們的目的可以說已經達到了,而且還不錯,因為這是不限層數的(以前 CMS 常說的“無限級”分類)。——其實,一般情況下,層數超過三層就很多,很復雜了,一般用戶如無特殊需求,也用不上這么多層。于是,在給定層數的約束下,可以寫標準的 SQL 來完成該任務——盡管有點寫死的感覺~~

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4FROM category AS t1LEFT JOIN category AS t2 ON t2.parentId = t1.idLEFT JOIN category AS t3 ON t3.parentId = t2.idLEFT JOIN category AS t4 ON t4.parentId = t3.idWHERE t1.id= 1

SQL,雙親節點

 

相應地給出查找所有父節點的方法(獲取祖先 Ancestors,就是把 id 和 parentId 反過來)

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4  
FROM category AS t1  
 LEFT JOIN category AS t2 ON t2.id= t1.parentId 
 LEFT JOIN category AS t3 ON t3.id= t2.parentId 
 LEFT JOIN category AS t4 ON t4.id= t3.parentId

WHERE t1.id= 10優化版本

但是生成的結果和第一個例子相比起來有點奇怪,而且不好給 Java 用,——那就再找找其他例子

SELECT    
            p1.id,
            p1.name,
            p1.parentId as parentId,
            p2.parentId as parent2_id,
            p3.parentId as parent3_id,
            p4.parentId as parent4_id,
            p5.parentId as parent5_id,
   p6.parentId as parent6_id
FROM category p1
LEFT JOIN   category p2 on p2.id = p1.parentId 
LEFT JOIN   category p3 on p3.id = p2.parentId 
LEFT JOIN   category p4 on p4.id = p3.parentId  
LEFT JOIN   category p5 on p5.id = p4.parentId  
LEFT JOIN   category p6 on p6.id = p5.parentId
WHERE 1 IN   (p1.parentId, 
                   p2.parentId, 
                   p3.parentId, 
                   p4.parentId, 
                   p5.parentId, 
                   p6.parentId)

ORDER BY 1, 2, 3, 4, 5, 6, 7; 這個總算像點樣子了,結果是這樣子的。

SQL,雙親節點

 

相應地給出查找所有父節點的方法(獲取祖先 Ancestors,就是把 id 和 parentId 反過來, 還有改改 IN 里面的字段名) 

SELECT           p1.id,         p1.name,         p1.parentId as parentId,         p2.parentId as parent2_id,         p3.parentId as parent3_id  FROM  category p1   LEFT JOIN  category p2 on p2.parentId  = p1.id  LEFT JOIN  category p3 on p3.parentId  = p2.id  WHERE 9 IN  (p1.id,              p2.id,              p3.id)    ORDER BY 1, 2, 3; 

這樣就很通用啦~無論你 SQLite 還是 MySQL。

其他查詢:

查詢直接子節點的總數:

SELECT c.*,    (SELECT COUNT(*) FROM category c2 WHERE c2.parentId = c.id)     AS direct_childrenFROM category c

•使用 with 語句遞歸,通俗易懂的例子(英文),我第一個成功的例子就是從這里 copy 的,另外還可以查層數 level 和反向的父節點:https://www.valentina-db.com/dokuwiki/doku.php?id=valentina:articles:recursive_query

•標準寫法的出處(英文):http://stackoverflow.com/questions/20215744/how-to-create-a-mysql-hierarchical-recursive-query

•很好的總結貼(英文):http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

•SQlite with 語句用法中文翻譯(太晦澀,不懂鳥) http://blog.csdn.net/aflyeaglenku/article/details/50978986

•利用閉包做的樹結構(書上說這個方法最好,但同時覺得也很高級,英文)http://charlesleifer.com/blog/querying-tree-structures-in-sqlite-using-python-and-the-transitive-closure-extension/

以上這篇SQL 雙親節點查找所有子節點的實現方法就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持VeVb武林網。



注:相關教程知識閱讀請移步到MSSQL教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产精品人久久电影| 精品中文字幕视频| 国产精品久久久久77777| 日韩精品一二三四区| 久久精品精品电影网| 清纯唯美亚洲激情| 国产精品日日摸夜夜添夜夜av| 日韩精品中文字幕在线观看| 久热精品视频在线观看一区| 日本精品视频在线观看| 久久在线免费观看视频| 国产精品永久免费在线| 国产aaa精品| 欧美丰满老妇厨房牲生活| 久久99青青精品免费观看| 国产精品视频男人的天堂| 国产suv精品一区二区三区88区| 国产日韩欧美综合| 综合国产在线观看| 精品精品国产国产自在线| 国产精品视频区| 97不卡在线视频| 日韩中文字幕视频在线观看| 91国产一区在线| 亚洲国产精品va在线看黑人动漫| 欧美人成在线视频| 欧美黑人一级爽快片淫片高清| 九九热这里只有在线精品视| 亚洲欧美另类在线观看| 91精品久久久久久久久久| 国产精品一区二区3区| 国产伦精品一区二区三区精品视频| 国产午夜精品理论片a级探花| 欧美激情一区二区三区高清视频| 国产视频久久久久久久| 欧美日韩免费网站| 深夜福利91大全| 青青草精品毛片| 久久香蕉频线观| 国产精品激情自拍| 国产成+人+综合+亚洲欧洲| 亚洲男人天堂2019| 亚洲精品美女久久久| 亚洲精品美女在线| 一个色综合导航| 久久韩剧网电视剧| 亚洲欧美日韩成人| 成人日韩在线电影| 一本大道香蕉久在线播放29| 亚洲女人被黑人巨大进入al| 日韩av理论片| 亚洲理论电影网| 在线观看国产欧美| 亚洲色在线视频| 国产精品h片在线播放| 国产精品美女网站| 日本亚洲欧洲色| 国产亚洲欧美另类中文| 色综合久久天天综线观看| 国产欧美日韩丝袜精品一区| 国产91成人在在线播放| 成人国产精品久久久| 91在线色戒在线| 亚洲精品98久久久久久中文字幕| 久久视频免费在线播放| 成人免费观看网址| 国产91精品网站| 欧美丝袜一区二区三区| 久久久国产在线视频| 尤物九九久久国产精品的分类| 欧美一级高清免费播放| 亚洲综合在线小说| 亚洲乱码一区二区| 久久久亚洲福利精品午夜| 亚洲欧洲日产国产网站| 亚洲精品日韩欧美| 国产精品美女主播| 在线精品视频视频中文字幕| 日韩中文视频免费在线观看| 午夜精品福利在线观看| 日韩电影大全免费观看2023年上| 国产精品美女999| 欧美激情精品久久久久久蜜臀| 中文字幕亚洲字幕| 高清欧美性猛交| 国产精品18久久久久久首页狼| 国产精品美女av| 国产一区二区在线免费| 国内久久久精品| 性日韩欧美在线视频| 亚洲国产欧美日韩精品| 日韩中文综合网| 国产精品jizz在线观看麻豆| 91九色视频导航| 日韩动漫免费观看电视剧高清| 国产欧美日韩精品在线观看| 97视频在线观看网址| 欧美日韩第一页| 亚洲国产精品成人va在线观看| 欧美久久精品一级黑人c片| 日韩美女视频在线观看| 欧美一区二区三区免费视| 疯狂做受xxxx欧美肥白少妇| 亚州国产精品久久久| 亚洲va久久久噜噜噜久久天堂| 一本色道久久88精品综合| 国产一区二区三区久久精品| 国产伦精品一区二区三区精品视频| 亚洲欧美综合另类中字| 国产精品对白刺激| 亚洲欧美日韩天堂| 91亚洲精品在线| 欧美精品激情在线观看| 久久99精品久久久久久噜噜| 亚洲一区中文字幕| 国产精品久久9| 亚洲乱码一区二区| 日韩欧美在线网址| 久久亚洲精品小早川怜子66| 久久久av网站| 日韩中文字幕免费看| 精品国偷自产在线视频| 欧美黄色三级网站| 亚洲精品国产精品自产a区红杏吧| 欧美极品xxxx| 欧美精品videossex性护士| 国产精品综合网站| 日韩免费在线电影| 国产精品久在线观看| 亚洲一区二区三区777| 国产精品一区二区三| 精品成人69xx.xyz| 欧美国产第二页| 怡红院精品视频| 国产精品第3页| 91精品在线观| 国产一区玩具在线观看| 午夜精品久久久久久久久久久久| 成人精品一区二区三区电影黑人| 日韩av在线不卡| 亚洲欧美日韩国产精品| 国产欧美va欧美va香蕉在| 精品亚洲男同gayvideo网站| 国产精品一区av| 97在线视频免费观看| 欧美日韩国产在线播放| 97人人做人人爱| 国语自产在线不卡| 国产精品一区二区三区毛片淫片| 国内精品久久久久影院优| 色偷偷9999www| 国产精品亚洲欧美导航| 亚洲一区二区免费| 国产精品xxxxx| 亚洲色图激情小说| 国产亚洲视频在线观看| 成人黄色片网站| 成人美女av在线直播| 日韩欧美中文在线| 欧美综合在线第二页| 久久久精品久久久| 久久久久久综合网天天| 国产精品日韩在线播放| 国内精品伊人久久|