如果向 select 添加其他列,Redshift 将返回 null

问题描述 投票:0回答:1

我有以下选择语句

select 

ss.market || ss.speed_group || ss.dprt_time_segment || ss.company|| ss.season, 

f9.market, --( ( (select * from filter_9_criteria) < .5 and f9.market is not null) or ( (select * from filter_9_criteria) >= .5 ) ),
f8.market, --( ( (select * from filter_8_criteria) < .5 and f8.market is not null) or ( (select * from filter_8_criteria) >= .5 ) ),
f7.market, --( ( (select * from filter_7_criteria) < .5 and f7.market is not null) or ( (select * from filter_7_criteria) >= .5 ) ),
f6.market, --( ( (select * from filter_6_criteria) < .5 and f6.market is not null) or ( (select * from filter_6_criteria) >= .5 ) ),
f5.market, --( ( (select * from filter_5_criteria) < .5 and f5.market is not null) or ( (select * from filter_5_criteria) >= .5 ) ),
f4.market, --( ( (select * from filter_4_criteria) < .5 and f4.market is not null) or ( (select * from filter_4_criteria) >= .5 ) ),
f3.market, --( ( (select * from filter_3_criteria) < .5 and f3.market is not null) or ( (select * from filter_3_criteria) >= .5 ) ),
f2.market, --( ( (select * from filter_2_criteria) < .5 and f2.market is not null) or ( (select * from filter_2_criteria) >= .5 ) ),
f1.market, --( ( (select * from filter_1_criteria) < .5 and f1.market is not null) or ( (select * from filter_1_criteria) >= .5 ) ),
f0.market --,( ( (select * from filter_0_criteria) < .5 and f0.market is not null) or ( (select * from filter_0_criteria) >= .5 ) )

from select_statement ss

left join ** each filter_cte on market, speed_group, dprt_time_segment, company, season **

where ss.market || ss.speed_group || ss.dprt_time_segment || ss.company|| ss.season = ** specific group that I know exists in all filter_cte's **

每个过滤器_#_criteria 所在位置

select count(*)::float / (select count(*)::float from filter_cte_#) as val from filter_cte_# where year in (2020,2021) 

f# 是对应的filter_cte_# 的别名。

filter_cte 用于检查每个 cte 中是否存在选择顶部的组(market、speed_group 等),其中每个 filter_cte 除了查看的时间范围外都是相同的。

如果我如图所示运行(右侧注释),那么我得到 f9.market,...,f0.market 都不如预期为空,但如果我取消注释右侧,则所有市场返回 null 并且右侧计算仅基于

(select * from filter_0_criteria) >= .5 )
(忽略
or
左侧的所有内容)。

redshift 是否由于计算费用而返回 null?我可以理解右侧的列有问题,但它会泄漏到市场中,并在不应该的情况下将其返回为空(因为我知道每个过滤器 cte 都匹配,如果我在右侧运行,则所有市场都会填充)。

我尝试过不使用filter_#_criteria并直接从过滤器cte中选择(即

( ( (select count(*)::float / (select count(*)::float from filter_cte_#) from filter_cte_# where year in (2020,2021) ) < .5 or f#.market is not null) or ( (select count(*)::float / (select count(*)::float from filter_cte_#) from filter_cte_# where year in (2020,2021)) >= .5))

但这又返回了同样的问题。我还尝试在右侧逻辑语句的每个单独部分周围添加括号。

如果我仅取消注释其中之一(例如filter_9_criteria),那么该市场(f9.market)将返回 null,其余的则不会。所以我也不明白两者是如何以这种方式联系在一起的。

sql amazon-web-services join amazon-redshift common-table-expression
1个回答
0
投票

我以前见过这种事。 Redshift 使用多个查询优化器,并根据查看查询计划的“智能”代理来选择要使用的优化器。我怀疑如果您在两个版本(注释和未注释)上运行 EXPLAIN,您会发现计划在基本级别上有所不同(不仅仅是添加一些步骤)。

虽然这些优化器中的一个 Redshift 错误总是有可能的(我见过一次),但事实很少是这样,而且我已经处理过数十个客户坚持认为 Redshift 有错误的实例。问题通常是查询中的模糊性以及各种优化器做出不同的假设。

您已经简化了查询并使用了一些速记符号,因此我正在对发生的情况做出最好的猜测。

您有 10 个相关子查询,它们似乎想要返回布尔值。这些上没有显示 WHERE 子句,这可能是产生歧义的地方。在这种情况下,相关子查询通常是原因,因为就编译器/优化器而言,它们的定义往往是松散的。将它们重写为窗口函数通常会增加严谨性,从而有助于解决这种情况。

CTE 代码对于理解正在发生的事情可能很重要。有问题的优化器可能会重用 CTE 和顶部选择或相关子查询之间的代码。了解是否发生这种情况的一种方法是将 CTE 查询的结果保存到临时表并查看结果是否会改变。

你的 JOIN 树和 WHERE 子句对我来说也是不透明的,我看不出是否有任何计算重用的机会。但根据我的经验,我会首先关注条件子查询。这种查询语法似乎会引起歧义。

© www.soinside.com 2019 - 2024. All rights reserved.