我使用的系统将分层数据存储在父子表(邻接表)中:
代码 | 家长代码 | 分拣机 | 字幕 |
---|---|---|---|
A | (空) | 0 | ... |
B | A | 0 | ... |
C | A | 1 | ... |
D | C | 0 | ... |
E | D | 0 | ... |
F | C | 1 | ... |
G | C | 2 | ... |
Sorter
列确定兄弟姐妹的顺序。代码 D、F、G 是兄弟姐妹(=同一父母的孩子),并且排序器可能会更改,例如如果插入新行并将其放置在最后一个兄弟之前。例如,最后一个兄弟可以是像“其他”这样的类别,当然“其他”始终是最后一个兄弟,即使稍后插入更详细的类别也是如此。
简而言之:树可能会生长和变化。
对于下游系统,我需要这棵树的“定序器” - 一个深度优先的树遍历,枚举从节点 1(第一个根)到最后一个的行。这可以单独在 T-SQL (SQL Server 2016) 中完成吗?
我之前用 CTE 做了一些实验,我成功了,例如制作一个用于计算级别和完整路径的 CTE。但这些数据在兄弟排序器上不受影响;如果第一个和最后一个同级更改位置,级别和完整路径不会更改。定序器必须这样做。
作为后备措施,我设法在 C# 应用程序中的 Infragistics UltraTree 中绘制树,然后递归迭代。这可行,但是是一种非 SQL 方法。 SQL 可以自己完成这项工作吗?
这可能会帮助您开始:
CREATE TABLE data_table (
dt_code VARCHAR(2) NOT NULL,
dt_parent_code VARCHAR(2),
dt_sorter INT,
);
INSERT data_table VALUES ( 'A', NULL, 0 );
INSERT data_table VALUES ( 'B', 'A', 0 );
INSERT data_table VALUES ( 'C', 'A', 1 );
INSERT data_table VALUES ( 'D', 'C', 0 );
INSERT data_table VALUES ( 'E', 'D', 0 );
INSERT data_table VALUES ( 'F', 'C', 1 );
INSERT data_table VALUES ( 'G', 'C', 2 );
使用 CTE 查询 - 将 WHERE 子句中的 dt_code 设置为要从层次结构中提取的根值...
WITH cte ( code, parent_code, level, path )
AS
(
-- Anchor member ...
SELECT dt_code, dt_parent_code, 1 AS level,
CAST( dt_sorter AS VARCHAR( MAX ) ) AS path
FROM data_table
WHERE dt_code = 'A'
UNION ALL
-- Recursive member ...
SELECT dt_code, dt_parent_code, cte.level + 1 AS level,
CAST( cte.path + '.' + CAST( dt_sorter AS VARCHAR ) AS VARCHAR( MAX ) ) AS path
FROM data_table, cte
WHERE dt_parent_code = cte.code
)
SELECT code, parent_code, level, path
FROM cte
WHERE code = cte.code
ORDER BY path;
输出:
code parent_code level path
---- ----------- ----- ----
A (null) 1 0
B A 2 0.0
C A 2 0.1
D C 3 0.1.0
E D 4 0.1.0.0
F C 3 0.1.1
G C 3 0.1.2
希望有帮助。