Sql 在左联接和where表达式中未使用检索行的CTE
我已经在AmazonRedshift上编写了一个SQL查询,我面临一个CTE不返回行的问题 查询正在从CTE No1检索id和时间戳,并在比较CTE No1的时间戳字段与CTE No2,3,4,5,5的时间戳字段后,返回CTE No2,3,4,6的字段。更准确地说,下面是我的SQL查询的伪代码,我希望它是可以理解的。请不要太注意超前和滞后函数。查询问题本质上比可能出现的问题简单得多,并且是关于CTE的0行,但它们用于最终查询的where条件,如何解释这些情况Sql 在左联接和where表达式中未使用检索行的CTE,sql,null,amazon-redshift,common-table-expression,Sql,Null,Amazon Redshift,Common Table Expression,我已经在AmazonRedshift上编写了一个SQL查询,我面临一个CTE不返回行的问题 查询正在从CTE No1检索id和时间戳,并在比较CTE No1的时间戳字段与CTE No2,3,4,5,5的时间戳字段后,返回CTE No2,3,4,6的字段。更准确地说,下面是我的SQL查询的伪代码,我希望它是可以理解的。请不要太注意超前和滞后函数。查询问题本质上比可能出现的问题简单得多,并且是关于CTE的0行,但它们用于最终查询的where条件,如何解释这些情况 with CTE1 AS (SEL
with CTE1 AS
(SELECT timestamp1, id
from table1
where ...
...
...)
, CTE2 as
(select timestamp2,
id,
field1,
field2,
LAG(timestamp2,1) over partition by id order by timestamp2 as timestamp2_previous,
LEAD(timestamp2,1) over partition by id order by timestamp2 as timestamp2_next
from table2)
, CTE3 as
(select timestamp3,
id,
field1,
field2,
LAG(timestamp3,1) over partition by id order by timestamp3 as timestamp3_previous,
LEAD(timestamp3,1) over partition by id order by timestamp3 as timestamp3_next
from table3)
, CTE4 as
(select timestamp4,
id,
field1,
field2,
LAG(timestamp4,1) over partition by id order by timestamp4 as timestamp4_previous,
LEAD(timestamp4,1) over partition by id order by timestamp4 as timestamp4_next
from table4)
, CTE5 as
(select timestamp5,
id,
field1,
field2,
LAG(timestamp5,1) over partition by id order by timestamp5 as timestamp5_previous,
LEAD(timestamp5,1) over partition by id order by timestamp5 as timestamp5_next
from table5)
, CTE6 as
(select timestamp6,
id,
field1,
field2,
LAG(timestamp6,1) over partition by id order by timestamp6 as timestamp6_previous,
LEAD(timestamp6,1) over partition by id order by timestamp6 as timestamp6_next
from table6)
select cte1.id,
cte1.timestamp1,
case when cte1.timestamp1<cte2.timestamp2 and cte2.timestamp2_previous is null then cte2.field1 else cte2.field2,
case when cte1.timestamp1<cte3.timestamp3 and cte3.timestamp3_previous is null then cte3.field1 else cte3.field2,
case when cte1.timestamp1<cte4.timestamp4 and cte4.timestamp4_previous is null then cte4.field1 else cte4.field2,
case when cte1.timestamp1<cte5.timestamp5 and cte5.timestamp5_previous is null then cte5.field1 else cte5.field2,
case when cte1.timestamp1<cte6.timestamp6 and cte6.timestamp6_previous is null then cte6.field1 else cte6.field2
from cte1
left join cte2 on cte1.id=cte2.id
left join cte3 on cte1.id=cte3.id
left join cte4 on cte1.id=cte4.id
left join cte5 on cte1.id=cte5.id
left join cte6 on cte1.id=cte6.id
where 1
and
-- conditions for CTE2
( case when cte1.timestamp1 < cte2.timestamp2 and cte2.timestamp2_previous is null then 1=1
else cte1.timestamp1 > cte2.timestamp2 end
and
CASE
WHEN cte2.timestamp2_next is not null THEN cte1.timestamp1 < cte2.timestamp2_next ELSE 1=1
END
)
-- conditions for CTE3
( case when cte1.timestamp1 < cte3.timestamp3 and cte3.timestamp3_previous is null then 1=1
else cte1.timestamp1 > cte3.timestamp3 end
and
CASE
WHEN cte3.timestamp3_next is not null THEN cte1.timestamp1 < cte3.timestamp3_next ELSE 1=1
END
)
-- conditions for CTE4
( case when cte1.timestamp1 < cte4.timestamp4 and cte4.timestamp4_previous is null then 1=1
else cte1.timestamp1 > cte4.timestamp4 end
and
CASE
WHEN cte4.timestamp4_next is not null THEN cte1.timestamp1 < cte4.timestamp4_next ELSE 1=1
END
)
-- conditions for CTE5
( case when cte1.timestamp1 < cte5.timestamp5 and cte5.timestamp5_previous is null then 1=1
else cte1.timestamp1 > cte5.timestamp5 end
and
CASE
WHEN cte5.timestamp5_next is not null THEN cte1.timestamp1 < cte5.timestamp5_next ELSE 1=1
END
)
-- conditions for CTE6
( case when cte1.timestamp1 < cte6.timestamp6 and cte6.timestamp6_previous is null then 1=1
else cte1.timestamp1 > cte6.timestamp6 end
and
CASE
WHEN cte6.timestamp6_next is not null THEN cte1.timestamp1 < cte6.timestamp6_next ELSE 1=1
END
)
问题是,在第一个之后的一些CTE没有返回特定id的记录。我测试了特定id的代码,而CTE3没有返回该id的行。
在这些情况下,最终的where条件(都与AND连接)将评估其中没有记录的CTE,并返回0行,因为操作为TRUE和NULL,即使所有其他CTE都有该id的数据,并且查询结果应该检索它们的数据
如何检索此类情况的结果,并在引用带now行的CTE的结果字段中获取NULL?正如@JNevill所说,答案是将where条件移动到联接。为了让您了解其工作原理,cte1和cte2之间的连接变成:
在cte1.id=cte2.id和cte1.timestamp