SQL 中表示的展平树结构
Flatten tree structure represented in SQL
我正在使用工程计算包并尝试在允许 SQL 查询的内置报告工具中从中提取一些信息
简写例子SQL table如下:
Id | Description | Ref
---|---------------------
1 | system 1 |
3 | block 4 | 6
3 | block 4 | 1
5 | formula1 | 3
6 | f |
7 | something | 1
9 | cheese | 5
"Ref" 列标识的行是其他项目的子记录。
我想要做的是 运行 一个查询,该查询将生成一个列表,该列表将显示出现在每个页面上的所有项目。从上面的 table 可以看出 "ID" 不是唯一键;每个项目都可以出现在 table 内的多个位置。在上面的例子中:
- ID 5 是 ID3 的子项目
- ID 3 是 ID 1 AND ID 6 的子项
- ID 1 和 ID 6 不是任何项的子项
它实际上代表了一个树结构:
ID 1
+-------- ID 7
|---- ID 3
+---- ID 5
+---- ID 9
ID 6
+---- ID 3
+---- ID 5
+---- ID 9
我希望找出每个顶级项目下出现哪些项目(因此最终结果应该是 table,其中 "Ref" 列中仅出现顶级项目) :
Id | Description | Ref
---|---------------------
1 | system 1 |
3 | block 4 | 6
3 | block 4 | 1
5 | formula1 | 1
5 | formula1 | 6
6 | f |
9 | cheese | 1
9 | cheese | 6
7 | something | 1
树结构总共可以有5层深
我一直在尝试使用左联接来构建页面引用列表,但我认为我还需要合并结果 tables(因为很明显像 ID=9 的行, ID=5, and ID = 6 必须在最终结果集中重复)。开始有点乱了!
WITH A
AS (SELECT *
FROM [RbdBlocks]),
B
AS (SELECT [x].[Id],
[x].[Description],
[x].[Page] AS Page1,
[y].[Page] AS Page2,
FROM A AS x
LEFT OUTER JOIN
A AS y
ON y.Id = x.Page)
SELECT *
FROM B
上面给了我一些嵌套引用,但我不确定是否有更好的方法来将这些数据放在一起,并管理递归而不是仅仅将查询集复制 4 次?
看看 Recursive Common Table Expressions(CTE)。他们应该能够完全满足您的需求。
查看 SQL 文档页面上的 Example D。
基本上你在你的情况下会做的是:
- 在 CTE 的 "anchor member" 中,select 所有顶级项目
- 在 CTE 的 "recursive member" 中,将所有嵌套子项加入顶级项
递归 CTE 并不容易理解,因此请务必仔细阅读文档。
我正在使用工程计算包并尝试在允许 SQL 查询的内置报告工具中从中提取一些信息
简写例子SQL table如下:
Id | Description | Ref
---|---------------------
1 | system 1 |
3 | block 4 | 6
3 | block 4 | 1
5 | formula1 | 3
6 | f |
7 | something | 1
9 | cheese | 5
"Ref" 列标识的行是其他项目的子记录。
我想要做的是 运行 一个查询,该查询将生成一个列表,该列表将显示出现在每个页面上的所有项目。从上面的 table 可以看出 "ID" 不是唯一键;每个项目都可以出现在 table 内的多个位置。在上面的例子中:
- ID 5 是 ID3 的子项目
- ID 3 是 ID 1 AND ID 6 的子项
- ID 1 和 ID 6 不是任何项的子项
它实际上代表了一个树结构:
ID 1
+-------- ID 7
|---- ID 3
+---- ID 5
+---- ID 9
ID 6
+---- ID 3
+---- ID 5
+---- ID 9
我希望找出每个顶级项目下出现哪些项目(因此最终结果应该是 table,其中 "Ref" 列中仅出现顶级项目) :
Id | Description | Ref
---|---------------------
1 | system 1 |
3 | block 4 | 6
3 | block 4 | 1
5 | formula1 | 1
5 | formula1 | 6
6 | f |
9 | cheese | 1
9 | cheese | 6
7 | something | 1
树结构总共可以有5层深
我一直在尝试使用左联接来构建页面引用列表,但我认为我还需要合并结果 tables(因为很明显像 ID=9 的行, ID=5, and ID = 6 必须在最终结果集中重复)。开始有点乱了!
WITH A
AS (SELECT *
FROM [RbdBlocks]),
B
AS (SELECT [x].[Id],
[x].[Description],
[x].[Page] AS Page1,
[y].[Page] AS Page2,
FROM A AS x
LEFT OUTER JOIN
A AS y
ON y.Id = x.Page)
SELECT *
FROM B
上面给了我一些嵌套引用,但我不确定是否有更好的方法来将这些数据放在一起,并管理递归而不是仅仅将查询集复制 4 次?
看看 Recursive Common Table Expressions(CTE)。他们应该能够完全满足您的需求。
查看 SQL 文档页面上的 Example D。
基本上你在你的情况下会做的是:
- 在 CTE 的 "anchor member" 中,select 所有顶级项目
- 在 CTE 的 "recursive member" 中,将所有嵌套子项加入顶级项
递归 CTE 并不容易理解,因此请务必仔细阅读文档。