SQL Server 2012 - 在 WHERE 子句下有两个条件的递归 CTE
SQL Server 2012 - Recursive CTE with two conditions under WHERE clause
#1 编辑
我将 WHERE 子句中的 AND 更改为 OR,一切正常。但是我需要在 CTE 的递归部分使用 JOIN,问题又出现了,因为我不能在这里使用 OUTER JOIN。因此,我将 JOIN 更改为 OUTER APPLY 并且效果很好。
SQL Fiddle: http://sqlfiddle.com/#!18/9eecb/81809
我正在尝试实现一个递归 CTE,它接收两个年龄并递增这些年龄,直到它们都等于 120。问题是当我尝试向递归部分添加 WHERE 子句时,谓词被完全忽略:
;with age_cte as (
select
26 as wife_age,
28 as husband_age
union all
select
age_cte.wife_age + 1,
age_cte.husband_age + 1
from age_cte
where wife_age < 120 and husband_age < 120
) select * from age_cte;
一旦其中一个年龄达到 120 岁,CTE 就会停止。例子中,当丈夫的年龄等于120岁时,妻子的年龄为118岁,则停止计算。
我知道数据库遵循查询逻辑。我的问题是我应该如何将正确的逻辑应用于该 CTE,即当一个年龄超过 120 直到另一个年龄达到 120 时 return NULL?
Example:
. .
. .
. .
118 120
119 NULL
120 NULL
我尝试使用带有两个锚点和两个递归部分的 CTE,如下所示 documentation example ("H. Using multiple anchor and recursive members"):
create table age (
wife_age int,
husband_age int
);
insert into age values(26, 28);
;with age_cte as (
-- first anchor
select
wife_age
from age
union
-- second anchor
select
husband_age
from age
union all
select
age_cte.wife_age + 1
from age_cte
where wife_age < 120
union all
--
select
age_cte.husband_age + 1
from age_cte
where husband_age < 120
) select * from age_cte;
我遗漏了一些东西,因为它在第二个递归查询中为 "husband_age" 提供了 "Invalid column name"。
我也试过这个查询
;with age_cte as (
select
26 as wife_age,
28 as husband_age
union all
select
case when age_cte.wife_age + 1 > 120 then null else age_cte.wife_age + 1 end,
case when age_cte.husband_age + 1 > 120 then null else age_cte.husband_age + 1 end
from age_cte
where 120 >= case
when age_cte.wife_age + 1 < age_cte.husband_age + 1 then
age_cte.wife_age + 1
else
age_cte.husband_age + 1
end
) select * from age_cte;
但要么它给出一个无限循环,要么年龄达到 119 永远不会达到 120。
这应该可以满足您的要求:
with age_cte as (
select 26 as wife_age, 28 as husband_age
union all
select
case when wife_age < 120 then wife_age + 1 end,
case when husband_age < 120 then husband_age + 1 end
from age_cte
where wife_age < 120 or husband_age < 120
)
select * from age_cte;
即:
你希望在递归查询的 where
子句中使用 or
而不是 and
,因此查询一直进行到两个年龄都达到 120
当年龄超过 120
时,您可以在 select
中使用条件逻辑来生成 null
s
wife_age | husband_age
-------: | ----------:
26 | 28
27 | 29
28 | 30
29 | 31
...
116 | 118
117 | 119
118 | 120
119 | null
120 | null
#1 编辑
我将 WHERE 子句中的 AND 更改为 OR,一切正常。但是我需要在 CTE 的递归部分使用 JOIN,问题又出现了,因为我不能在这里使用 OUTER JOIN。因此,我将 JOIN 更改为 OUTER APPLY 并且效果很好。
SQL Fiddle: http://sqlfiddle.com/#!18/9eecb/81809
我正在尝试实现一个递归 CTE,它接收两个年龄并递增这些年龄,直到它们都等于 120。问题是当我尝试向递归部分添加 WHERE 子句时,谓词被完全忽略:
;with age_cte as (
select
26 as wife_age,
28 as husband_age
union all
select
age_cte.wife_age + 1,
age_cte.husband_age + 1
from age_cte
where wife_age < 120 and husband_age < 120
) select * from age_cte;
一旦其中一个年龄达到 120 岁,CTE 就会停止。例子中,当丈夫的年龄等于120岁时,妻子的年龄为118岁,则停止计算。
我知道数据库遵循查询逻辑。我的问题是我应该如何将正确的逻辑应用于该 CTE,即当一个年龄超过 120 直到另一个年龄达到 120 时 return NULL?
Example:
. .
. .
. .
118 120
119 NULL
120 NULL
我尝试使用带有两个锚点和两个递归部分的 CTE,如下所示 documentation example ("H. Using multiple anchor and recursive members"):
create table age (
wife_age int,
husband_age int
);
insert into age values(26, 28);
;with age_cte as (
-- first anchor
select
wife_age
from age
union
-- second anchor
select
husband_age
from age
union all
select
age_cte.wife_age + 1
from age_cte
where wife_age < 120
union all
--
select
age_cte.husband_age + 1
from age_cte
where husband_age < 120
) select * from age_cte;
我遗漏了一些东西,因为它在第二个递归查询中为 "husband_age" 提供了 "Invalid column name"。
我也试过这个查询
;with age_cte as (
select
26 as wife_age,
28 as husband_age
union all
select
case when age_cte.wife_age + 1 > 120 then null else age_cte.wife_age + 1 end,
case when age_cte.husband_age + 1 > 120 then null else age_cte.husband_age + 1 end
from age_cte
where 120 >= case
when age_cte.wife_age + 1 < age_cte.husband_age + 1 then
age_cte.wife_age + 1
else
age_cte.husband_age + 1
end
) select * from age_cte;
但要么它给出一个无限循环,要么年龄达到 119 永远不会达到 120。
这应该可以满足您的要求:
with age_cte as (
select 26 as wife_age, 28 as husband_age
union all
select
case when wife_age < 120 then wife_age + 1 end,
case when husband_age < 120 then husband_age + 1 end
from age_cte
where wife_age < 120 or husband_age < 120
)
select * from age_cte;
即:
你希望在递归查询的
where
子句中使用or
而不是and
,因此查询一直进行到两个年龄都达到 120当年龄超过 120
时,您可以在
select
中使用条件逻辑来生成 null
s
wife_age | husband_age -------: | ----------: 26 | 28 27 | 29 28 | 30 29 | 31 ... 116 | 118 117 | 119 118 | 120 119 | null 120 | null