CTE-取得家长

时间:2019-02-14 13:15:59

标签: sql sql-server

我知道CTE存在很多问题,但我仍然不知道该怎么做。 我有带有列的表Messages:id和previousMessageId。如何获得ID = 957的父母-应该是950。

table Messages
--------------
id  | previousMessageId
957 | 956
956 | 950
950 | NULL

这是我的查询

WITH previous AS 
( 
    SELECT id  
    FROM Messages 
    WHERE id = 957 

    UNION ALL 

    SELECT cur.id 
    FROM Messages cur
    INNER JOIN previous ON cur.previousMessageID = previous.id
) 
SELECT * FROM previous 

它给了我

957
958

但是结果应该是:950

3 个答案:

答案 0 :(得分:3)

您可以尝试以下操作。

declare @table table(id int,   previousMessageId int)
insert into @table select 957 , 956
insert into @table select 956 , 950
insert into @table select 950 , NULL
insert into @table select 999 , 998
insert into @table select 998 , 997
insert into @table select 997 , NULL

;WITH previous 
     AS (SELECT id, 
                previousmessageid 
         FROM   @table 
         WHERE  id = 957
         UNION ALL 
         SELECT cur.id, 
                cur.previousmessageid 
         FROM   @table cur 
                INNER JOIN previous 
                        ON cur.id = previous.previousmessageid) 
SELECT ID 
FROM   previous 
WHERE  previousmessageid IS NULL 

在上面的示例中,ID 957为950,ID为999

答案 1 :(得分:0)

您可以使用第二列来表示父代ID。父层将具有一个空列,子​​层将随后引用父层。

WITH previous AS 
( 
SELECT id, null as parentid  
FROM Messages 
WHERE id = 957 

UNION ALL 

SELECT cur.id, cur.previousMessageID 
FROM Messages cur
INNER JOIN previous ON cur.previousMessageID = previous.id
) 
SELECT ParentID FROM previous where ParentID is not null 

答案 2 :(得分:0)

declare @table table(id int,   previousMessageId int)
insert into @table select 957 , 956
insert into @table select 956 , 950
insert into @table select 950 , NULL
insert into @table select 999 , 998
insert into @table select 998 , 997
insert into @table select 997 , NULL;

with cte as (
    -- base case - get all records with no parent
    select *, 
        cast(concat('/', id, '/') as varchar(max)) as [path],
        id as [root]
    from @table
    where previousMessageId is null

    union all

    -- recursive step
    select child.*, 
        concat(parent.path, child.id, '/'),
        parent.root
    from @table as child
    join cte as parent
        on parent.id = child.previousMessageId
)
select *
from cte
where id = 957;

最终输出中的root列是该祖先行中以该特定ID结尾的第一行。至于我的实现方式,诀窍本质上是始终将parent.root推进递归步骤。