如何在SQL Server中选择父行和子行

时间:2013-03-04 11:51:08

标签: sql sql-server select common-table-expression

我想从下表中选择与user_id 53(父母和孩子)相关的所有itens。它应该是:1,2,4,8,9。

my_table
--------------------------------------------
id    parent_id   user_id   sequence   depth
--------------------------------------------
1     null        50        1          1
2     1           52        1.2        2
3     1           52        1.3        2
4     2           53        1.2.4      3
5     2           52        1.2.5      3
6     3           52        1.3.6      3
7     3           51        1.3.7      3
8     4           51        1.2.4.8    4
9     4           51        1.2.4.9    4

使用CTE,我可以选择所有孩子或父母,但我不能只用一个查询选择孩子和父母。下面是我用来选择孩子的cte。

物品和儿童

with cte as (
    select t.id, t.parent_id, t.user_id 
    from my_table t 
    where t.user_id=53

    union all

    select t.id, t.parent_id, t.user_id 
    from my_table t
    inner join cte c on (c.parent_id=t.id)
)
select t.* from cte t;

项目和父母

with cte as (
    select t.id, t.parent_id, t.user_id 
    from my_table t 
    where t.user_id=53

    union all

    select t.id, t.parent_id, t.user_id 
    from my_table t
    inner join cte c on (c.id=t.parent_id)
)
select t.* from cte t;

感谢。

2 个答案:

答案 0 :(得分:4)

你有序列非常方便。父母的序列与您要查找的序列的初始子集匹配。对于孩子们来说也是如此,但反之亦然。

以下内容接近你想要的内容:

select mt.*
from (select sequence from my_table where USER_ID = 53) theone join
     my_table mt
     on mt.sequence like theone.sequence+ '%' or
        theone.sequence like mt.sequence + '%'

但是,您必须小心10匹配1。所以,让我们在适当的时候增加一个额外的时期:

select mt.*
from (select sequence from my_table where USER_ID = 53) theone join
     my_table mt
     on mt.sequence like theone.sequence+ '.%' or
        theone.sequence like mt.sequence + '.%'

答案 1 :(得分:0)

问题在于,您需要递归 SELECT。 DBMS不是为这样的查询而制作的。但它当然是可能的。

SELECT t1.* FROM Table1 t1 WHERE user_id = 53

UNION ALL

SELECT t2.* FROM Table1 t1, Table1 t2
WHERE
  (t1.id = t2.parent_id OR t1.parent_id = t2.id) AND t1.user_id = 53

此查询将为您提供每个1度亲属。

对于递归SELECT,请查看此处:Recursive select in SQL


您的查询解决方案:http://sqlfiddle.com/#!6/e1542/10/0

with cte as (
    select t.id, t.parent_id, t.user_id 
    from Table1 t 
    where t.user_id=53
),

cte1 as (
    select t.id, t.parent_id, t.user_id 
    from cte t

    union all

    select t.id, t.parent_id, t.user_id 
    from Table1 t
    inner join cte1 c on (c.parent_id=t.id)
),

cte2 as (
    select t.id, t.parent_id, t.user_id 
    from cte t

    union all

    select t.id, t.parent_id, t.user_id 
    from Table1 t
    inner join cte2 c on (c.id=t.parent_id)
)

select t.* from cte1 t

UNION

select t.* from cte2 t