获取没有CTE的所有父ID

时间:2017-08-14 13:28:42

标签: sql sql-server

我需要编写一个查询,从一个表中返回所有父ID,该表具有child_idparent_id的简单结构给定child_id

但是,所有这些业务都发生在一个较大的查询中,该查询有一些外部适用产生问题的child_id,因此如果我使用CTE,那么我无法传递输入CTE本身的参数。更大的查询是这样的:

SELECT * FROM some_table
OUTER APPLY (some query here that generates as child id) AS generated_child_id
WHERE some_table.id IN (LIST_OF_ALL_PARENTS_OF_CHILD_ID_PLUS_CHILD_ID_ITSELF)

如果我使用选择父ID的CTE,则generated_child_id在其中不可用,这是整点。我要么需要另一种方法,要么我需要在WHERE子句中定义CTE,我不知道该怎么做。

1 个答案:

答案 0 :(得分:0)

在查询期间,CTE确实可以被视为“好像”是视图/表格。您可以对CTE定义进行彻底检查,然后在查询时应用过滤器,这些过滤器应该在应用时尽可能地向下推。

例如,我使用以下查询创建了一个包含约100万行的表:

create table T (ParentID int not null, ChildID int not null)
;With Numbers as (
    select ROW_NUMBER() OVER (ORDER BY so1.object_id) as n
    from sys.objects so1
    cross join sys.objects so2
    cross join sys.objects so3
)
insert into T(ParentID,ChildID)
select n1.n,n2.n
from Numbers n1
inner join
Numbers n2
    on
        n1.n = n2.n - 1
create index IX_Parent_Child on T(ParentID,ChildID)
create index IX_Child_Parent on T(ChildID,ParentID)

这是一个特别讨厌的父/子设置,因为它是一条长链,所以最后一个孩子最终通过每隔一行与第一个父亲相关。

然后我使用CTE查询它:

;With Ancestors as (
    select ParentID as AncestorID, ChildID
    from T
    union all
    select t.ParentID,a.ChildID
    from
        Ancestors a
            inner join
        T t
            on
                a.AncestorID = t.ChildID
)
select
    AncestorID
from
    (select 1) t(t)
        cross apply
    (select 15) as u(ChildID)
        cross apply
    (select AncestorID from Ancestors where ChildID = u.ChildID) v

检查查询计划。计划中的任何一点都没有实现约100万行 - 只需实际完成查询所需的13/14行。

因此,在所有子项中编写一个通用的CTE,然后像查询任何其他表/视图一样从中查询/过滤 - 并且信任优化器做正确的事情。