问题描述
这是我的桌子:
CREATE TABLE IF NOT EXISTS NODE
(
UUID VARCHAR NOT NULL,PARENT_UUID VARCHAR NULL,NAME VARCHAR NOT NULL,PRIMARY KEY (UUID)
);
这是我的测试数据:
INSERT INTO node (uuid,parent_uuid,name)
VALUES
('dfca05bc-551d-4e3d-87aa-7dd7d29539f6',null,'Computers'),('ff83eb99-ea2c-4d11-8ebe-4600445a3bda','Food'),('405f0267-fa22-4cac-a397-c430be221828','Drinks'),('e79ecefa-c3e2-400f-aab4-2d28fcd3a832','dfca05bc-551d-4e3d-87aa-7dd7d29539f6','Monitors'),('61a94b77-56c2-48ff-b869-39305648a25c','System blocks'),('5d88a9b7-7ffe-45e5-b35f-9350072ed619','Mother boards'),('5994c39d-c4ea-454c-ae57-118392b93f66','Different'),('d1c994fe-f3ec-40ed-aace-5221c026c0ea','5994c39d-c4ea-454c-ae57-118392b93f66','Keyboards'),('7757aa9b-abee-4d30-89d3-79f77613b5e8','Mice'),('33d93c3a-1c2d-44b9-8fac-3f83074104a5','Joysticks'),('f13bb023-47b2-473a-83b0-4223ff6e28b9','e79ecefa-c3e2-400f-aab4-2d28fcd3a832','Size 14'),('312a4e56-71ef-4372-a556-17ace15197e6','Size 15'),('c525374c-6a06-46e4-98c8-bc669e811e22','Size 16');
我想得到 a) 所有父母和他们的兄弟姐妹 b) 节点的所有兄弟姐妹。例如,如果我选择了 Joysticks 节点,那么我想获得
- 计算机
- 不同
- 操纵杆
- 键盘
- 小鼠
- 监视器
- 母板
- 系统块
- 不同
- 饮料
- 食物
如您所见,未选择属于监视器的大小 14、15、16 节点。
WITH RECURSIVE theparents (uuid,name,level) AS (
SELECT uuid,0 AS level,FROM node
WHERE uuid = '33d93c3a-1c2d-44b9-8fac-3f83074104a5'
UNION ALL
SELECT a.uuid,a.parent_uuid,a.name,b.level + 1 as level
FROM node a
INNER JOIN theparents b ON b.parent_uuid = a.uuid
),thesiblings AS (
SELECT a.uuid,b.level as level
FROM node a
INNER JOIN theparents b ON b.parent_uuid = a.parent_uuid OR (b.parent_uuid IS NULL AND a.parent_uuid IS NULL)
)
SELECT * FROM thesiblings;
此查询选择所有节点,但不进行排序。是否可以使用 sql 对它们进行排序,或者只能手动完成?
解决方法
您只需将 tree
加入 node
。唯一的问题是保持它根据树遍历顺序排序。试试这个,在 MySql 8.0 中测试
编辑
现在按基于名称的路径排序,20 是表中的最大名称长度
WITH RECURSIVE tree (uuid,parent_uuid,name,level,path) AS
(
SELECT uuid,0 level,cast(Rpad(name,20,' ') as char(200)) path
FROM nodes
WHERE uuid = '33d93c3a-1c2d-44b9-8fac-3f83074104a5'
UNION ALL
SELECT a.uuid,a.parent_uuid,a.name,level-1,concat(Rpad(a.name,' '),'>',path)
FROM nodes a
INNER JOIN tree b ON b.parent_uuid = a.uuid
)
select uuid,level /*,path */
from (
select n.uuid,n.name,max(-level) over() + level + 1 level,concat(substring(first_value(path) over(order by level),1,(20+1) * (max(-level) over() + level +1 )),n.name) path
from tree t
join nodes n on n.parent_uuid = t.uuid
-- no children for starting node
and t.level <> 0
union all
-- roots
select uuid,Rpad(name,' ')
from nodes
where parent_uuid is null
) t
order by path