2016-12-30 70 views
2

我有一个表的ServiceItem具有Id,ParentId和一些属性,如Name,Description等。层次结构的最大级别为2。我需要查询一些条件选择行,例如Name = '123'和其父行即可水木清华这样的:从表中选择层次结构

Id ParentId Name 
1 NULL  '12' 
2 1   '123' 

我已经试过这样:

SELECT 
    * 
FROM ServiceItem si 
WHERE si.Name = '123' 
    OR EXISTS (
     SELECT 
      * 
     FROM ServiceItem syst 
      JOIN ServiceItem si2 
       ON si2.ParentId = syst.Id 
     WHERE syst.Id = si.ParentId 
      AND si2.Name = '123' 

    ) 

但它会返回父项及其全部子项。有没有机会用一个查询来做到这一点?我正在使用T-SQL来做到这一点。

它不同于this question,因为我需要一堆行,不仅我的查询中的路径和条件可能会有所不同。

+0

可能的重复[如何遍历表中的id与parentId?](http://stackoverflow.com/question s/37197500/how-to-traverse-a-path-in-a-table-with-id-parentid) –

+0

@a_horse_with_no_name不,这不是我要找的。 –

+0

[Sql server CTE和递归示例]的可能重复(http://stackoverflow.com/questions/14274942/sql-server-cte-and-recursion-example)。您必须修改查询以使用树的底部而不是顶部来启动树,但它本质上是相同的语法。 –

回答

1

您可以使用公用表表达式递归:

WITH cte AS 
    (
    SELECT  * 
    FROM  ServiceItem 
    WHERE  Name = '123' 
    UNION ALL 
    SELECT  * 
    FROM  ServiceItem si 
    INNER JOIN cte 
      ON cte.ParentId = si.Id 
) 
SELECT * FROM cte 

为了更深入的例子,看到this Q&A

+0

@trinkot是的,我工作就像我需要它。谢谢。 –

0
WITH cte AS 
    (
    SELECT  * 
    FROM  ServiceItem 
    WHERE  Name = '123' 
    UNION ALL 
    SELECT  * 
    FROM  ServiceItem si 
    INNER JOIN cte 
      ON cte.ParentId = si.Id 
) 
SELECT * FROM cte 

这是一个很好的查询,但我也发现了这一个:

SELECT 
    * 
FROM ServiceItem si 
WHERE si.Name = '123' 
    OR EXISTS (
     SELECT 
      * 
     FROM ServiceItem si2 
     WHERE si2.Name = '123' 
      and si2.ParentId = si.Id 
    )