ItemId Name parentId
1 A null
2 b null
3 c 1
4 d 2
5 e 3
6 f 4
7 g 2
嗨,我需要帮助创建SQL查询。我有一个包含3列itemid,name,parentitemid的表。我需要一个sql查询结果父子关系。如果parentitemid id为null则表示root。请帮助
我需要像。
这样的数据<1><3><5></5> </3></1>
答案 0 :(得分:1)
例如,您可以使用:
WITH HierarchicalTable
AS
(
SELECT Id, ParentId, Name, 0 as [Level]
FROM YourTable
WHERE ParentId IS NULL
UNION ALL
SELECT YourTable.Id, YourTable.ParentId, YourTable.Name, [Level] + 1
FROM YourTable
JOIN HierarchicalTable ON HierarchicalTable.Id = YourTable.ParentId
)
SELECT [Level], Name FROM HierarchicalTable
答案 1 :(得分:0)
这是一个过于复杂的解决方案,但它可以解决您的问题:
DECLARE @temp TABLE (ItemId int, Name char(1), parentId int,l int)
DECLARE @xml TABLE (s nvarchar(max), e nvarchar(max), parentId int, itemid int)
DECLARE @l int
;WITH cte AS (
SELECT *
FROM (VALUES
(1, 'a', NULL),(2, 'b', NULL),(3, 'c', 1),(4, 'd', 2),(5, 'e', 3),(6, 'f', 4),(7, 'g', 2)
) as t(ItemId, Name, parentId)
--Here we create recursive cte to obtain levels of nesting
), res AS (
SELECT *,
1 [Level]
FROM cte c
where parentId IS null
UNION ALL
SELECT c.*,
[Level]+1
FROM res r
INNER JOIN cte c
ON c.parentId = r.ItemId
)
--put results into temp table
INSERT INTO @temp
SELECT *
FROM res
--obtain max level
SELECT @l = MAX(l)
FROM @temp
--from max level to 1 begin
WHILE @l > 0
BEGIN
--if there is nodes with same parentid - concatinating them
UPDATE x
SET x.e = x.e + v.s + v.e
FROM @xml x
INNER JOIN @xml v
ON v.parentId = x.parentId and v.e !=x.e;
--here we merge table with results
-- first run <e></e>
-- next run <c><e></e></c>
-- next run <a><c><e></e></c></a>
MERGE @xml AS target
USING (
SELECT '<'+ Name +'>' as s,'</'+ Name + '>' as e, parentId, ItemId
FROM @temp
WHERE l = @l
) as source
ON target.parentid = source.itemid
WHEN NOT MATCHED THEN INSERT VALUES (source.s, source.e, source.parentId, source.ItemId)
WHEN MATCHED THEN
UPDATE
SET target.s = source.s + target.s,
target.e = target.e + source.e,
target.parentid = source.parentid,
target.itemid = source.itemid;
--next level down
SET @l = @l - 1
END
SELECT x --CAST(x as xml)
FROM (
SELECT s+e as x,
DENSE_RANK() OVER (PARTITION BY itemid ORDER BY s ASC) as rn
--need that column to obtain first one of every string for itemid
FROM @xml
) as c
WHERE c.rn = 1
--FOR XML PATH ('')
输出将是:
x
<a><c><e></e></c></a>
<b><d><f></f></d><g></g></b>
如果您移除--
附近的FOR XML PATH ('')
并在上次查询中将此SELECT x --CAST(x as xml)
更改为此SELECT CAST(x as xml)
,您将收到以下信息:
<a>
<c>
<e />
</c>
</a>
<b>
<d>
<f />
</d>
<g />
</b>