您可以用下面的查詢實現這一目標:
select id,
name,
parent_id
from (select * from products
order by parent_id, id) base,
(select @pv := '1') tmp
where find_in_set(parent_id, @pv) > 0
and @pv := concat(@pv, ',', id)
這裏是一個fiddle基於問題提供的一個。
@pv := '1'
中指定的值應設置爲要選擇所有後代的父代的id。
如果家長有多個孩子,這也可以工作。但是,要求每個記錄parent_id < id
,否則結果將不完整。
另請注意,對於非常大的數據集,此解決方案可能會變慢,因爲find_in_set
操作並不是在列表中找到數字的最理想方式,當然不是按照相同順序達到大小的列表幅度與返回記錄的數量一樣。
注意:如果你想有父節點本身也包含在結果集,然後前綴與where
子句中的id
值的關注的上述SQL
之前如下:
select id,
name,
parent_id
from products
where id = '1'
union
...
替代1:CONNECT BY
其他一些數據庫具有特定的分層查找語法,例如Oracle數據庫上的CONNECT BY
子句。 MySql不提供這樣的語法。
備選方案2:更聰明的標識符
事情變得容易得多,如果你指定包含分層信息id
值。例如,你的情況,這可能是這樣的:
ID | NAME
1 | P
1-1 | C1
1-2 | C2
1-1-1 | C3
1-1-1-1 | C4
那麼你的選擇是這樣的:
select id,
name
from products
where id like '1-%'
方案3:重複自連接
如果你知道您的分層樹可以變得有多深的上限,您可以使用像這樣的標準sql
:
select 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 1 in (p1.parent_id,
p2.parent_id,
p3.parent_id,
p4.parent_id,
p5.parent_id)
order by 1, 2, 3, 4, 5, 6;
看到這個fiddle
的where
條件指定要檢索的後代父母哪一方。您可以根據需要使用更多級別擴展此查詢。
這是一個分層查詢。 MySQL基本上不支持分層和遞歸查詢。要麼你需要改變你的數據結構或使用遞歸存儲過程。一個簡單的'select'語句不能做你想做的事。 –
我想在你的第二個例子中你缺少'5 | C4 | 4' – Axalix
類似的問題http://stackoverflow.com/questions/5291054/generating-depth-based-tree-from-hierarchical-data-in-mysql-no-ctes/5291159#5291159 – Suing