場景:
數(shù)據(jù)庫中的數(shù)據(jù)存在父子關(guān)系(單繼承,每一條記錄只有一個父記錄). 如果要查詢一條記錄以及他的所有子記錄,或者要查詢一條記錄以及他的所有父記錄.那么遞歸查詢就再合適不過了.可以簡化復(fù)雜的SQL語句。
現(xiàn)在數(shù)據(jù)庫有一張dictionary表,用于存放業(yè)務(wù)相關(guān)字典項
id,name,parent_id
id | name | parentId |
---|---|---|
1 | 字典1 | NULL |
1-1 | 字典1-1 | 1 |
1-2 | 字典1-2 | 1 |
2 | 字典2 | NULL |
2-1 | 字典2-1 | 2 |
WITH RECURSIVE dict AS (
SELECT *
FROM dictionary
WHERE id= '1'
union ALL
SELECT dictionary.*
FROM dictionary,
dict
WHERE dictionary.parent_id = dict.id
)
SELECT id AS id, name as name, parent_id as parentId
FROM dict
ORDER BY name
查詢結(jié)果
id | name | parentId |
---|---|---|
1 | 字典1 | NULL |
1-1 | 字典1-1 | 1 |
1-2 | 字典1-2 | 1 |
WITH RECURSIVE dict AS (
SELECT *
FROM dictionary
WHERE id= '2-1'
union ALL
SELECT dictionary.*
FROM dictionary,
dict
WHERE dictionary.id = dict.parent_id
)
SELECT id AS id, name as name, parent_id as parentId
FROM dict
ORDER BY name
查詢結(jié)果
id | name | parentId |
---|---|---|
2 | 字典2 | NULL |
2-1 | 字典2-1 | 2 |
- sql中WITH xxxx AS () 是對一個查詢子句做別名,同時數(shù)據(jù)庫會對該子句生成臨時表;
WITH RECURSIVE 則是一個遞歸的查詢子句,他會把查詢出來的結(jié)果再次代入到查詢子句中繼續(xù)查詢
?
//todo 此種方式都是查詢一棵樹,如果結(jié)果list中有多棵截斷的樹,需要遞歸查出來最頂層的parentId節(jié)點(diǎn)集合(就是找出 父節(jié)點(diǎn)對象不存在的就是頂層),然后循環(huán)這個集合挨個拼成這些樹,并且再放進(jìn)一個tree集合中,從而形成一個多樹的json,但是此種方法有一個很大的問題:效果上看導(dǎo)致小樹的頂層位置都從最前面開始了,與實際不否,實際中應(yīng)該是錯開的幾棵樹,綜述實際開發(fā)中不會有這樣的結(jié)果list。