MySQ樹狀結構資料 遞迴查詢

2021-08-16 03:08:05 字數 3758 閱讀 3045

for example:

create

table products(

id int,

name varchar(100),

parent_id int

);insert

into products values

(15, 'category15', 0), -- not a descendant of

19(16, 'category16', 15), -- not a descendant of

19(19, 'category19', 0),

(20, 'category20', 19), -- level

1(21, 'category21', 20), -- level

2(22, 'category22', 21), -- level

3(23, 'category23', 19), -- level

1(24, 'category24', 21), -- level

3(25, 'category25', 22), -- level

4(26, 'category26', 22), -- level

4(27, 'category26', 25), -- level

5(30, 'category21', 16);

-- not a descendant of 19

solution:

select  id,

name,

parent_id

from (select * from products

order

by parent_id, id) products_sorted,

(select @pv := '19') initialisation

where find_in_set(parent_id, @pv)

and length(@pv := concat(@pv, ',', id))

result:

name parent_id

20 category20 19

23 category23 19

21 category21 20

22 category22 21

24 category24 21

25 category25 22

26 category26 22

27 category26 25

指定的值@pv := 『19』應該設定為id要選擇所有子項的父id。

如果父節點有多個子節點,這一樣有效。但是,要求每條記錄都滿足條件parent_id < id,否則結果不準確。

該查詢使用特定的mysql語法:在執行期間分配和修改變數。對執行順序做了一些假設:

from項首先被執行。所以這就是@pv初始化的地方。

where子句按照從from別名中檢索的順序執行每條記錄。所以這是乙個條件被放置的地方,只包括父母已經被識別為在後代樹中的記錄(主要父母的所有後代都被逐步新增到@pv)。

本節中的條件按where順序進行評估,一旦總體結果確定,評估就會中斷。因此,第二個條件必須排在第二位,因為它將它新增id到父列表中,並且只有在id傳遞第乙個條件時才會發生。length函式僅用於確保此條件始終為真,即使該pv字串會產生虛假值。

所以,人們可能會發現這些假設風險太高而無法依賴 - 它們沒有檔案保證,即使它一貫地工作,當您將此查詢用作檢視或子檢視時,執行順序在理論上可能仍會發生變化。

另外注意,如果是非常大的資料,這個解決方案可能會變慢,因為find_in_set操作並不是在列表中找到數字的最理想方式,當然不是在與數量相同的數量級達到大小的列表中記錄返回。

方案1: with recursive,connect by

現在越來越多的資料庫都支援以下標準:1999 iso標準with [recursive]語法的遞迴查詢(如postgres的8.4+,sql server的2005+,db2,甲骨文11gr2的+,sqlite的3.8.4+,火鳥2.1+,h2,的hypersql 2.1.0+,teradata的,mariadb 10.2.2+)。從版本8.0開始,mysql也將支援它。使用該語法,查詢如下所示:

( select id,

name,

parent_id

from products

where parent_id = 19

union all

select p.id,

p.name,

p.parent_id

from products p

inner join cte

onp.parent_id = cte.id

)select * from cte;

一些資料庫有用於分層查詢的替代非標準語法,例如connect byoracle資料庫上可用的子句。db2也支援這種替代語法。

mysql 5.7不支援。如果你的資料庫版本支援這種語法時,那最好了。如果不支援,請考慮以下選擇。

方案2:id標示路徑

如果id包含路徑層次結構資訊,那就很好處理。例如,在你的情況下,這可能看

id       | name

19| category1

19/1

| category2

19/1/1

| category3

19/1/1/1

| category4 --

select  id,

name

from products

where id like

'19/%'

方案3:同表連線

如果知道層次結構樹有幾層,可以試試下面的sql:

select      p6.parent_id as parent6_id,

p5.parent_id as parent5_id,

p4.parent_id as parent4_id,

p3.parent_id as parent3_id,

p2.parent_id as parent2_id,

p1.parent_id as parent_id,

p1.id as product_id,

p1.name

from products p1

left

join products p2 on p2.id = p1.parent_id

left

join products p3 on p3.id = p2.parent_id

left

join products p4 on p4.id = p3.parent_id

left

join products p5 on p5.id = p4.parent_id

left

join products p6 on p6.id = p5.parent_id

where

19in (p1.parent_id,

p2.parent_id,

p3.parent_id,

p4.parent_id,

p5.parent_id,

p6.parent_id)

order

by1, 2, 3, 4, 5, 6, 7;

from: 谷歌翻譯

PostgreSQL遞迴查詢實現樹狀結構查詢

在postgresql的使用過程中發現了乙個很有意思的功能,就是對於需要類似於樹狀結構的結果可以使用遞迴查詢實現。比如說我們常用的公司部門這種資料結構,一般我們設計表結構的時候都是類似下面的sql,其中parent id為null時表示頂級節點,否則表示上級節點id。create table dep...

樹狀遞迴查詢

樹狀等級查詢 所有資料 從mysql裡面輸出的全部是字串型別 list array array cat id 8 cat name 分類fff sort order 30 parent id 1 array cat id 1 cat name 分類aaa sort order 50 parent i...

Oracle 遞迴遍歷樹狀結構

connect by prior 是結構化查詢中用到的,其基本語法是 select from tablename start with 條件1 connect by prior 條件2 where 條件3 從root往樹末梢遞迴 sql select from tablename start wit...