需要帮助形成SQL查询

时间:2016-05-20 08:31:14

标签: sql-server

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>

2 个答案:

答案 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>