为了加强对sql处理树状结构的理解,这里以一个真实的案例进行讲解说明:
背景:部门表是树状结构
需求1: 将每个部门的所有的父级节点水平展示出来
需求2: 为每个部门打标归类,父级任意一级节点中含有1的归类成’aaaa’,父级任意一级节点中含有2的归类成’bbbb’,否则归类成’其它’;
示例:这里提供了部门表伪表供测试
SELECT *
FROM VALUES
('1','ab','0')
,('2','ac','0')
,('11','ad','1')
,('12','ae','1')
,('21','af','2')
,('22','ag','2')
,('111','ah','11')
,('112','ai','11')
,('1111','aj','111')
,('1112','ak','111')
,('2201','al','22')
,('2022','am','22') as(id,name,pid)
;
处理这个问题的思路就是将先将部门表扁平化处理,先计算出每个部门ID气对应的所有的父部门ID,并把他们存放到数组结构中,然后再与分类进行比较
注:这里伪表与自己join了4次,至于实际项目中join几次,需要结合实际数据来看,没有统一值的(join次数过多可能会影响性能,join次数过少可能有些层级比较深的部门并没有完整递归所有的父部门ID)
SELECT id1
,name1
,level
,level_arr
,(
CASE WHEN ARRAY_CONTAINS(level_arr,'1') = true THEN 'aaaaa'
WHEN ARRAY_CONTAINS(level_arr,'2') = true THEN 'bbbb'
ELSE '其它'
END
) type
FROM (
SELECT id1
,name1
,CONCAT_WS(',',id1,id2,id3,id4,id5) level
,SPLIT(CONCAT_WS(',',id1,id2,id3,id4,id5),',') level_arr
FROM (
SELECT t1.id id1
,t1.name name1
,IF(t2.id IS NULL,'',t2.id) id2
,IF(t3.id IS NULL,'',t3.id) id3
,IF(t4.id IS NULL,'',t4.id) id4
,IF(t4.pid IS NULL,'',t4.pid) id5
FROM (
SELECT *
FROM VALUES
('1','ab','0')
,('2','ac','0')
,('11','ad','1')
,('12','ae','1')
,('21','af','2')
,('22','ag','2')
,('111','ah','11')
,('112','ai','11')
,('1111','aj','111')
,('1112','ak','111')
,('2201','al','22')
,('2022','am','22') as(id,name,pid)
) t1
LEFT JOIN (
SELECT *
FROM VALUES
('1','ab','0')
,('2','ac','0')
,('11','ad','1')
,('12','ae','1')
,('21','af','2')
,('22','ag','2')
,('111','ah','11')
,('112','ai','11')
,('1111','aj','111')
,('1112','ak','111')
,('2201','al','22')
,('2022','am','22') as(id,name,pid)
) t2
ON t1.pid = t2.id
LEFT JOIN (
SELECT *
FROM VALUES
('1','ab','0')
,('2','ac','0')
,('11','ad','1')
,('12','ae','1')
,('21','af','2')
,('22','ag','2')
,('111','ah','11')
,('112','ai','11')
,('1111','aj','111')
,('1112','ak','111')
,('2201','al','22')
,('2022','am','22') as(id,name,pid)
) t3
ON t2.pid = t3.id
LEFT JOIN (
SELECT *
FROM VALUES
('1','ab','0')
,('2','ac','0')
,('11','ad','1')
,('12','ae','1')
,('21','af','2')
,('22','ag','2')
,('111','ah','11')
,('112','ai','11')
,('1111','aj','111')
,('1112','ak','111')
,('2201','al','22')
,('2022','am','22') as(id,name,pid)
) t4
ON t3.pid = t4.id
)
)
;