获取 SQL 中没有搜索到的 id 的兄弟姐妹的直接层次结构
Get direct hierarchy in SQL without siblings of searched id
我有一个非常简单的 table 类型,它包含 ID、ParentID 和 Name。我需要的是从一个 ID 获取完整的层次结构,但不包括所搜索 ID 的兄弟姐妹。我写了以下 SQL,
;WITH cte AS (
SELECT ID, ParentID, [Name]
FROM [Types]
WHERE ID=246
UNION ALL
SELECT t1.ID, t1.ParentID, t1.[Name]
FROM [Types] t1
INNER JOIN cte ON cte.ID=t1.ParentID
)
SELECT * FROM cte
这给了我 table 的完整层次结构(最顶层的父级是 id '246'):
到目前为止,还不错。我现在想从查询中获得的是 ID 的完整层次结构:1384,但没有 ID 1384 的兄弟姐妹(以及兄弟姐妹的子女、孙子女等)。所以它应该 return 以下结果:
+------+----------+------------------+
| ID | ParentID | Name |
+------+----------+------------------+
| 246 | 2 | Approvals |
+------+----------+------------------+
| 1384 | 246 | ProductStatus |
+------+----------+------------------+
| 1517 | 1384 | NewStatus |
+------+----------+------------------+
| 1520 | 1384 | NewSiblingStatus |
+------+----------+------------------+
| 1519 | 1517 | NewNewStatus |
+------+----------+------------------+
我已经阅读了各种关于检索层次结构的文章,但到目前为止还没有进一步解决这个问题,也没有找到有类似问题的人。
一种方法是使用两个递归通用 table 表达式。一个获得 parents,另一个获得 children。然后你可以 union
他们得到你想要的结果 - union
(而不是 union all
)是为了消除初始节点上的重复项。
WITH
cte_children AS (
SELECT ID, ParentID, [Name], 0 lvl
FROM [Types]
WHERE ID = 1384
UNION ALL
SELECT t.ID, t.ParentID, t.[Name], lvl - 1
FROM [Types] t
INNER JOIN cte_children c ON c.ID = t.ParentID
)
cte_parents AS (
SELECT ID, ParentID, [Name], 0 lvl
FROM [Types]
WHERE ID = 1384
UNION ALL
SELECT t.ID, t.ParentID, t.[Name], lvl + 1
FROM [Types] t
INNER JOIN cte ON cte.ParentID = t.ID
)
SELECT * FROM cte_parents
UNION
SELECT * FROM cte_children
ORDER BY lvl
请注意,我在查询中添加了一个名为 lvl
的列,用于计算每个节点的深度(初始注释有 0
,parents 有负数 lvl
s, 和 children 有积极的 lvl
s) - 这很方便对最终结果集进行排序。
我有一个非常简单的 table 类型,它包含 ID、ParentID 和 Name。我需要的是从一个 ID 获取完整的层次结构,但不包括所搜索 ID 的兄弟姐妹。我写了以下 SQL,
;WITH cte AS (
SELECT ID, ParentID, [Name]
FROM [Types]
WHERE ID=246
UNION ALL
SELECT t1.ID, t1.ParentID, t1.[Name]
FROM [Types] t1
INNER JOIN cte ON cte.ID=t1.ParentID
)
SELECT * FROM cte
这给了我 table 的完整层次结构(最顶层的父级是 id '246'):
到目前为止,还不错。我现在想从查询中获得的是 ID 的完整层次结构:1384,但没有 ID 1384 的兄弟姐妹(以及兄弟姐妹的子女、孙子女等)。所以它应该 return 以下结果:
+------+----------+------------------+
| ID | ParentID | Name |
+------+----------+------------------+
| 246 | 2 | Approvals |
+------+----------+------------------+
| 1384 | 246 | ProductStatus |
+------+----------+------------------+
| 1517 | 1384 | NewStatus |
+------+----------+------------------+
| 1520 | 1384 | NewSiblingStatus |
+------+----------+------------------+
| 1519 | 1517 | NewNewStatus |
+------+----------+------------------+
我已经阅读了各种关于检索层次结构的文章,但到目前为止还没有进一步解决这个问题,也没有找到有类似问题的人。
一种方法是使用两个递归通用 table 表达式。一个获得 parents,另一个获得 children。然后你可以 union
他们得到你想要的结果 - union
(而不是 union all
)是为了消除初始节点上的重复项。
WITH
cte_children AS (
SELECT ID, ParentID, [Name], 0 lvl
FROM [Types]
WHERE ID = 1384
UNION ALL
SELECT t.ID, t.ParentID, t.[Name], lvl - 1
FROM [Types] t
INNER JOIN cte_children c ON c.ID = t.ParentID
)
cte_parents AS (
SELECT ID, ParentID, [Name], 0 lvl
FROM [Types]
WHERE ID = 1384
UNION ALL
SELECT t.ID, t.ParentID, t.[Name], lvl + 1
FROM [Types] t
INNER JOIN cte ON cte.ParentID = t.ID
)
SELECT * FROM cte_parents
UNION
SELECT * FROM cte_children
ORDER BY lvl
请注意,我在查询中添加了一个名为 lvl
的列,用于计算每个节点的深度(初始注释有 0
,parents 有负数 lvl
s, 和 children 有积极的 lvl
s) - 这很方便对最终结果集进行排序。