我需要编写一个查询,从一个表中返回所有父ID,该表具有child_id
和parent_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,我不知道该怎么做。
答案 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,然后像查询任何其他表/视图一样从中查询/过滤 - 并且信任优化器做正确的事情。