SQL Parent 的服务器 Make Tracks 或 Path 有很多 child
SQL Server Make Tracks or Path of Parent has many child
我有一个 Activity
table :
ActivityID ActivityName
-----------------------------
1 A1
2 A2
3 A3
4 A4
5 A5
6 A6
7 A7
8 A8
9 A9
10 A10
并在另一个 table 中将其与 parent child 关系关联为:
ParentActivityID ChildActivityID
-------------------------------------
1 2
1 3
2 4
2 5
3 6
4 7
5 7
6 8
7 9
8 9
9 10
我想写一个 SQL 查询,它将根据一个 parentActivity
中有多少 childActivity
进行跟踪,例如:
ActivityID TrackGroup
-------------------------
1 1
2 1
4 1
7 1
9 1
10 1
1 2
2 2
5 2
7 2
9 2
10 2
1 3
3 3
6 3
8 3
9 3
10 3
使用 sql 服务器 2008 r
根据您的 table 大小,这可能是地球上最慢的查询,但它确实满足了您的要求,我无法真正测试性能。
但是创建测试数据。
CREATE TABLE Activity
([ActivityID] int, [ActivityName] varchar(3))
;
INSERT INTO Activity
([ActivityID], [ActivityName])
VALUES
(1, 'A1'), (2, 'A2'), (3, 'A3'), (4, 'A4'), (5, 'A5'),
(6, 'A6'), (7, 'A7'), (8, 'A8'), (9, 'A9'), (10, 'A10')
;
CREATE TABLE RelatedActivity
([ParentActivityID] int, [ChildActivityID] int)
;
INSERT INTO RelatedActivity
([ParentActivityID], [ChildActivityID])
VALUES
(1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (4, 7),
(5, 7), (6, 8), (7, 9), (8, 9), (9, 10)
;
只是假设您可能 运行 这为 1 activity 所以我创建了一个变量并将其设置为第一个 ActivityID
DECLARE @ActivityID INT = 1
然后我使用递归 cte 来获取层次结构。我添加了一个 "Path" 字段,它只是将当前 ID 与以前的 ID 连接起来。
然后使用 SQL 2008 中的 ROW_NUMBER 函数并按 PATH
排序,我可以得到下一个 PATH
.
然后我可以比较当前路径的LEN和下一条路径的LEN,看看接下来是否有新的路径开始,如果有则给我当前路径。或者如果下一个 PATH 是 NULL 也得到它。
然后我使用字符串拆分函数将剩余的路径转换为行。
--Get hierarchy
;WITH cte AS
(
SELECT [ActivityID], NULL ParentActivityID, CAST([ActivityID] AS VARCHAR(255)) [Path]
FROM Activity WHERE [ActivityID] = @ActivityID
UNION ALL
SELECT ra.[ChildActivityID], ra.[ParentActivityID], CAST([Path] + '.' + CAST(ra.[ChildActivityID] AS VARCHAR(255)) AS VARCHAR(255))
FROM Activity a
JOIN RelatedActivity ra ON a.[ActivityID] = ra.[ChildActivityID]
JOIN cte ON ra.[ParentActivityID] = cte.[ActivityID]
)
SELECT *, ROW_NUMBER() OVER (ORDER BY [Path]) Rn
INTO #tempHierarchy
FROM cte
SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS ActivityID,
Rn AS TrackGroup
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY [Path]) Rn,
CAST('<XMLRoot><RowData>' + REPLACE([Path],'.','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM
#tempHierarchy t1
LEFT JOIN (SELECT [Path] [Next], ROW_NUMBER() OVER (ORDER BY [Path]) - 1 Rn FROM #tempHierarchy) t2 ON t1.Rn = t2.Rn
WHERE
[NEXT] IS NULL OR LEN([Next]) < LEN([Path])
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
我有一个 Activity
table :
ActivityID ActivityName
-----------------------------
1 A1
2 A2
3 A3
4 A4
5 A5
6 A6
7 A7
8 A8
9 A9
10 A10
并在另一个 table 中将其与 parent child 关系关联为:
ParentActivityID ChildActivityID
-------------------------------------
1 2
1 3
2 4
2 5
3 6
4 7
5 7
6 8
7 9
8 9
9 10
我想写一个 SQL 查询,它将根据一个 parentActivity
中有多少 childActivity
进行跟踪,例如:
ActivityID TrackGroup
-------------------------
1 1
2 1
4 1
7 1
9 1
10 1
1 2
2 2
5 2
7 2
9 2
10 2
1 3
3 3
6 3
8 3
9 3
10 3
使用 sql 服务器 2008 r
根据您的 table 大小,这可能是地球上最慢的查询,但它确实满足了您的要求,我无法真正测试性能。
但是创建测试数据。
CREATE TABLE Activity
([ActivityID] int, [ActivityName] varchar(3))
;
INSERT INTO Activity
([ActivityID], [ActivityName])
VALUES
(1, 'A1'), (2, 'A2'), (3, 'A3'), (4, 'A4'), (5, 'A5'),
(6, 'A6'), (7, 'A7'), (8, 'A8'), (9, 'A9'), (10, 'A10')
;
CREATE TABLE RelatedActivity
([ParentActivityID] int, [ChildActivityID] int)
;
INSERT INTO RelatedActivity
([ParentActivityID], [ChildActivityID])
VALUES
(1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (4, 7),
(5, 7), (6, 8), (7, 9), (8, 9), (9, 10)
;
只是假设您可能 运行 这为 1 activity 所以我创建了一个变量并将其设置为第一个 ActivityID
DECLARE @ActivityID INT = 1
然后我使用递归 cte 来获取层次结构。我添加了一个 "Path" 字段,它只是将当前 ID 与以前的 ID 连接起来。
然后使用 SQL 2008 中的 ROW_NUMBER 函数并按 PATH
排序,我可以得到下一个 PATH
.
然后我可以比较当前路径的LEN和下一条路径的LEN,看看接下来是否有新的路径开始,如果有则给我当前路径。或者如果下一个 PATH 是 NULL 也得到它。
然后我使用字符串拆分函数将剩余的路径转换为行。
--Get hierarchy
;WITH cte AS
(
SELECT [ActivityID], NULL ParentActivityID, CAST([ActivityID] AS VARCHAR(255)) [Path]
FROM Activity WHERE [ActivityID] = @ActivityID
UNION ALL
SELECT ra.[ChildActivityID], ra.[ParentActivityID], CAST([Path] + '.' + CAST(ra.[ChildActivityID] AS VARCHAR(255)) AS VARCHAR(255))
FROM Activity a
JOIN RelatedActivity ra ON a.[ActivityID] = ra.[ChildActivityID]
JOIN cte ON ra.[ParentActivityID] = cte.[ActivityID]
)
SELECT *, ROW_NUMBER() OVER (ORDER BY [Path]) Rn
INTO #tempHierarchy
FROM cte
SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS ActivityID,
Rn AS TrackGroup
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY [Path]) Rn,
CAST('<XMLRoot><RowData>' + REPLACE([Path],'.','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM
#tempHierarchy t1
LEFT JOIN (SELECT [Path] [Next], ROW_NUMBER() OVER (ORDER BY [Path]) - 1 Rn FROM #tempHierarchy) t2 ON t1.Rn = t2.Rn
WHERE
[NEXT] IS NULL OR LEN([Next]) < LEN([Path])
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)