是否有关于为什么的解释,以下无用的错误消息显示了它的工作方式,或者是否有其他文献记载的最佳实践来利用子查询中可能丢失的数据?
当我引用左联接到CTE的表中的字段时,BigQuery会产生一个令人困惑且无用的错误。
LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join.
我的特殊案例是尝试通过利用针对现有dates
表的子查询来计算两个日期之间的营业日。
当我将子查询作为select
ed字段引入时,下面的查询引发以下错误。
似乎对d2
的引用导致查询中断。
with
first_dates as (
select 1 as id, cast('2020-01-01' as date) as d
union all
select 2 as id, cast('2020-02-01' as date) as d
),
second_dates as (
select 1 as id, cast('2020-01-02' as date) as d
),
timelines as (
select
first_dates.id,
first_dates.d as d1,
second_dates.d as d2
from
first_dates
-- This is the only left join in my query, and looks fine to me!
left join second_dates using (id)
)
select
*,
(
select count(*)
from <my_example_dates_table>
where
date >= d1
and date < d2
and is_business_day
) as n_business_days
from
timelines
我当前的假设是BigQuery的后端将子查询转换为左联接,并在尝试这样做时遇到错误。如果是这样,我认为错误消息应该得到改善。
我发现许多SO链接都引用了相同的问题,但是我还没有找到任何答案来解释为什么确切地出现此错误,为什么错误消息如此无用以及是否有最佳实践在BigQuery中重新创建合理的查询模式。
因此,我恳请那些将其作为重复项关闭以使其保持打开状态的人,因为它专门询问有关为什么显示错误消息的答案。
已经回答了许多建议,它们提出了针对特定问题的替代方法:
答案 0 :(得分:1)
首先,考虑以下查询(从您的查询中简化):
with
first_dates as (
select 1 as id, cast('2020-01-01' as date) as d
union all
select 2 as id, cast('2020-02-01' as date) as d
)
select
*,
(
select count(*)
from utility.calendar -- just a simple calendar
where
calendar_date = d
) as n_business_days
from
first_dates
这将执行,如果您在BQ界面中查看“执行详细信息”,则确实可以看到联接正在发生。您的假设在这里似乎是正确的。
如果将子查询更改为calendar_date >= d
,则会收到LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join
错误。假设确实发生了子查询到左联接的转换,那么问题就变成了“为什么在左联接中需要相等?”
我不知道确切的原因,但是我的直觉是它与可伸缩性和查询成本估算有关。如果您的右侧表已分区,则不等式(>
,<
等)连接将无法从分区中受益,因为左侧的每一行都必须与整个右侧。
这里的解决方案是通常CROSS JOIN
然后进行过滤。这会将所有比较从join
子句移到where
子句。
select
id, d1, d2, count(*) as ct
from timelines
cross join <my_example_dates_table>
where date >= d1
and date < d2
and is_business_day
group by 1,2,3
答案 1 :(得分:1)
除了@rtenha评论。这是Bigquery的已知问题,可以在here
中进行跟踪此外,在这种情况下,建议将 <= 或> = 更改为 = 。
另外,以该查询为例:
选择 *, ( 选择 MIN(选择) 从 selected_t 哪里 选择> =请求)AS rounded_v FROM 小孩)
BigQuery小组建议的一种变通方法是,添加虚假的相等连接谓词,如下所示:
选择 *, ( 选择 MIN(选择) 从 selected_t 哪里 选择> =请求并选择0 *选择= 0 *请求)AS rounded_v