如何使用递归逻辑 return 仅 sql table 中的根行(SQL Server 2008 R2)
How to use recursive logic to return only the Root row in a sql table (SQL Server 2008 R2)
这是针对 SQL Server 2008 R2 的,我是 SQL 的新手,所以请尽可能具体。
Table1
内置了一些递归结构,其中 ParentId
是 Null
表示它是根,或者 ParentId
是 Id
Table1
中的另一行,将其表示为 child。
示例数据集:
Table1Id ParentId
--------------------------------------------
1 NULL
2 1
3 1
4 2
5 NULL
6 2
7 6
8 NULL
9 8
在上面的示例中,table 具有以下具有 3 个根节点的树结构:
Root 1 5 8
Child(teir1) 2 3 9
Child(teir2) 4 6
Child(tier3) 7
....
有没有办法在给定任何行 ID 的情况下仅 return 根行?例如:
InputId ReturnedRowId
----------------------------
1 1
2 1
3 1
4 1
5 5
6 1
7 1
8 8
9 8
如有任何帮助,我们将不胜感激。
使用 start with 和 connect by prior。在此处查看此文档
http://psoug.org/reference/connectby.html
我不确定 "connect by" 在 Oracle 以外的其他数据库中是否可用。看看吧。
你也可以试试with子句。这里有人试过。
Simulation of CONNECT BY PRIOR of ORACLE in SQL SERVER
作品有点像这样
with query1 as (select .... from .... where ....),
query2 as (select .... from .... where ....)
select ...
from query1 q1,
query2 q2
where q1.xxxxx = q2.xxxx
这是一个脚本,可以找到您拥有的节点 table 的根节点。它的作用:
- 在第一个 CTE 中,递归节点直到找到父节点。递归跟踪列
level
. 中的深度
- 在第二个 CTE 中,确定每个节点的最大深度:
max_level
。这是确定父级的深度。
- Select 最大深度的节点。
CREATE TABLE #tree(table1_id INT PRIMARY KEY,parent_id INT);
INSERT INTO #tree(table1_id,parent_id)VALUES
(1,NULL),(2,1),(3,1),(4,2),(5,NULL),(6,2),(7,6),(8,NULL),(9,8);
;WITH cte_tr AS (
SELECT table1_id, parent_id, level=0
FROM #tree
UNION ALL
SELECT t_c.table1_id, t_p.parent_id, level=t_c.level+1
FROM cte_tr AS t_c
INNER JOIN #tree AS t_p ON
t_p.table1_id=t_c.parent_id
WHERE t_p.parent_id IS NOT NULL
),
cte_ml AS (
SELECT table1_id, max_level=MAX(level)
FROM cte_tr
GROUP BY table1_id
)
SELECT cte_tr.table1_id, root_node=ISNULL(cte_tr.parent_id,cte_tr.table1_id)
FROM cte_tr
INNER JOIN cte_ml ON
cte_ml.table1_id=cte_tr.table1_id AND
cte_ml.max_level=cte_tr.level
ORDER BY cte_tr.table1_id
DROP TABLE #tree;
结果:
+-----------+-----------+
| table1_id | root_node |
+-----------+-----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 5 |
| 6 | 1 |
| 7 | 1 |
| 8 | 8 |
| 9 | 8 |
+-----------+-----------+
您可以使用 CTE 并遍历层次结构
IF OBJECT_ID('tempdb..#testData') IS NOT NULL
DROP TABLE #testData
CREATE TABLE #testData (
Table1Id INT
,ParentId INT NULL
)
INSERT INTO #testData ( Table1Id, ParentId )
VALUES
(1, NULL )
,(2, 1 )
,(3, 1 )
,(4, 2 )
,(5, NULL )
,(6, 2 )
,(7, 6 )
,(8, NULL )
,(9, 8 )
DECLARE @InputId INT
SET @InputId = 2 --<<--Change this as appropriate
;WITH cteTraverse
AS
(
SELECT
T.Table1Id, T.ParentId
FROM
#testData T
WHERE
Table1Id = @InputId
UNION ALL
SELECT
T1.Table1Id, T1.ParentId
FROM
#testData T1
INNER JOIN
cteTraverse T2 ON T1.Table1Id = T2.ParentId
)
SELECT
@InputId '@InputId', Table1Id 'ReturnedRowId'
FROM
cteTraverse
WHERE
ParentId IS NULL
这个查询完成工作。
with CTE as
(
Select Table1ID as ID, Table1ID as Ancestor, 0 as level
from Table1
UNION ALL
Select ID, ParentID, level + 1
from Table1
inner join CTE on CTE.Ancestor = Table1.Table1ID
where ParentID is not NULL
)
,
R_only as
(
Select ID as ID, MAX(level) as max_level
from CTE
group by ID
)
select CTE.ID, Ancestor
from CTE inner join R_only on CTE.ID = R_only.ID and CTE.level = R_only.max_level
order by CTE.ID
这是针对 SQL Server 2008 R2 的,我是 SQL 的新手,所以请尽可能具体。
Table1
内置了一些递归结构,其中 ParentId
是 Null
表示它是根,或者 ParentId
是 Id
Table1
中的另一行,将其表示为 child。
示例数据集:
Table1Id ParentId
--------------------------------------------
1 NULL
2 1
3 1
4 2
5 NULL
6 2
7 6
8 NULL
9 8
在上面的示例中,table 具有以下具有 3 个根节点的树结构:
Root 1 5 8
Child(teir1) 2 3 9
Child(teir2) 4 6
Child(tier3) 7
....
有没有办法在给定任何行 ID 的情况下仅 return 根行?例如:
InputId ReturnedRowId
----------------------------
1 1
2 1
3 1
4 1
5 5
6 1
7 1
8 8
9 8
如有任何帮助,我们将不胜感激。
使用 start with 和 connect by prior。在此处查看此文档
http://psoug.org/reference/connectby.html
我不确定 "connect by" 在 Oracle 以外的其他数据库中是否可用。看看吧。
你也可以试试with子句。这里有人试过。
Simulation of CONNECT BY PRIOR of ORACLE in SQL SERVER
作品有点像这样
with query1 as (select .... from .... where ....),
query2 as (select .... from .... where ....)
select ...
from query1 q1,
query2 q2
where q1.xxxxx = q2.xxxx
这是一个脚本,可以找到您拥有的节点 table 的根节点。它的作用:
- 在第一个 CTE 中,递归节点直到找到父节点。递归跟踪列
level
. 中的深度
- 在第二个 CTE 中,确定每个节点的最大深度:
max_level
。这是确定父级的深度。 - Select 最大深度的节点。
CREATE TABLE #tree(table1_id INT PRIMARY KEY,parent_id INT);
INSERT INTO #tree(table1_id,parent_id)VALUES
(1,NULL),(2,1),(3,1),(4,2),(5,NULL),(6,2),(7,6),(8,NULL),(9,8);
;WITH cte_tr AS (
SELECT table1_id, parent_id, level=0
FROM #tree
UNION ALL
SELECT t_c.table1_id, t_p.parent_id, level=t_c.level+1
FROM cte_tr AS t_c
INNER JOIN #tree AS t_p ON
t_p.table1_id=t_c.parent_id
WHERE t_p.parent_id IS NOT NULL
),
cte_ml AS (
SELECT table1_id, max_level=MAX(level)
FROM cte_tr
GROUP BY table1_id
)
SELECT cte_tr.table1_id, root_node=ISNULL(cte_tr.parent_id,cte_tr.table1_id)
FROM cte_tr
INNER JOIN cte_ml ON
cte_ml.table1_id=cte_tr.table1_id AND
cte_ml.max_level=cte_tr.level
ORDER BY cte_tr.table1_id
DROP TABLE #tree;
结果:
+-----------+-----------+
| table1_id | root_node |
+-----------+-----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 5 |
| 6 | 1 |
| 7 | 1 |
| 8 | 8 |
| 9 | 8 |
+-----------+-----------+
您可以使用 CTE 并遍历层次结构
IF OBJECT_ID('tempdb..#testData') IS NOT NULL
DROP TABLE #testData
CREATE TABLE #testData (
Table1Id INT
,ParentId INT NULL
)
INSERT INTO #testData ( Table1Id, ParentId )
VALUES
(1, NULL )
,(2, 1 )
,(3, 1 )
,(4, 2 )
,(5, NULL )
,(6, 2 )
,(7, 6 )
,(8, NULL )
,(9, 8 )
DECLARE @InputId INT
SET @InputId = 2 --<<--Change this as appropriate
;WITH cteTraverse
AS
(
SELECT
T.Table1Id, T.ParentId
FROM
#testData T
WHERE
Table1Id = @InputId
UNION ALL
SELECT
T1.Table1Id, T1.ParentId
FROM
#testData T1
INNER JOIN
cteTraverse T2 ON T1.Table1Id = T2.ParentId
)
SELECT
@InputId '@InputId', Table1Id 'ReturnedRowId'
FROM
cteTraverse
WHERE
ParentId IS NULL
这个查询完成工作。
with CTE as
(
Select Table1ID as ID, Table1ID as Ancestor, 0 as level
from Table1
UNION ALL
Select ID, ParentID, level + 1
from Table1
inner join CTE on CTE.Ancestor = Table1.Table1ID
where ParentID is not NULL
)
,
R_only as
(
Select ID as ID, MAX(level) as max_level
from CTE
group by ID
)
select CTE.ID, Ancestor
from CTE inner join R_only on CTE.ID = R_only.ID and CTE.level = R_only.max_level
order by CTE.ID