标准 SQL:使用 BETWEEN 通过两个条件进行 LEFT JOIN

Posted

技术标签:

【中文标题】标准 SQL:使用 BETWEEN 通过两个条件进行 LEFT JOIN【英文标题】:Standard SQL: LEFT JOIN by two conditions using BETWEEN 【发布时间】:2018-09-07 06:51:05 【问题描述】:

我在 BigQuery 中有以下查询:

#Standard SQL

SELECT *
FROM `Table_1`     
LEFT JOIN `Table_2` ON (timestamp BETWEEN TimeStampStart AND TimeStampEnd)

但我收到以下错误:

Error: LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join.

如果我使用 JOIN 而不是 LEFT JOIN,它可以工作,但我想保留 Table_1 中的所有行(还有那些与 Table_2 不匹配的行)

如何做到这一点?

【问题讨论】:

表1和表2是什么关系? ,如果没有关系,我更喜欢使用 Union 子句而不是在这种情况下不相关的连接 表 1 包含一列带有时间戳(和一些其他变量),而表 2 还包含一些其他变量加上两列带有时间戳(一个表示开始时间,另一个表示结束时间) .所以我想合并这两个表,这样当 Table_1 的时间戳位于开始时间和结束时间之间时,两个表的变量就会被连接/合并。 好的,你能试试 SELECT * FROM Table_1 LEFT JOIN Table_2 ON(table1.timestamp >= table2.TimeStampStart AND table1.timestamp 我试过了,但不幸的是我仍然遇到同样的错误。 您从谷歌搜索带有和不带标签的错误消息的众多点击中学到了什么? How to Ask 此外,左连接返回内连接行联合所有由空值扩展的不匹配的左表行。因此,您可以合并单独的部分。如果不是很明显,那肯定是一个常见问题。 PS请通过帖子编辑澄清,而不是cmets。 PS Re 用不等式替换:BigQuery does support inequality joins now - make sure to uncheck the "use legacy SQL option". 【参考方案1】:

这绝对是愚蠢的...但是如果您添加一个条件,将 table1 中的列与 table2 中的列相匹配,则相同的查询将起作用:

WITH Table_1 AS (
  SELECT CAST('2018-08-15' AS DATE) AS Timestamp, 'Foo' AS Foo
  UNION ALL
  SELECT CAST('2018-09-15' AS DATE), 'Foo'
), Table_2 AS (
  SELECT CAST('2018-08-14' AS DATE) AS TimeStampStart, CAST('2018-08-16' AS DATE) AS TimeStampEnd, 'Foo' AS Bar
)
SELECT *
FROM Table_1
LEFT JOIN Table_2 ON Table_1.Foo = Table_2.Bar AND Table_1.Timestamp BETWEEN Table_2.TimeStampStart AND Table_2.TimeStampEnd

查看您是否有其他可以使用的匹配条件(例如在相等时链接 table1 和 table2 的另一列)。

【讨论】:

我想通了!谢谢! 太棒了,这个答案让我很开心!【参考方案2】:

LEFT JOIN 总是等价于 UNION 的:

同一连接谓词的相同两个参数之间的 INNER JOIN,以及 第一个参数中未找到匹配行的行集(并使用从第二个参数保留的所有列正确扩展为空值)

后面的部分可以写成

SELECT T1.*, null as T2_C1, null as T2_C2, ... 从 T1 WHERE 不存在(从 T2 WHERE 中选择 *)

因此,如果您拼出 UNION,您应该能够到达那里。

【讨论】:

【参考方案3】:

有趣。这适用于标准 SQL:

select *
from (select 1 as x) a left join
     (select 2 as a, 3 as b) b
     on a.x between b.a and b.b

我怀疑您使用的是旧版 SQL。这样切换到标准 SQL。 (并在between 后面去掉括号。)

问题是:

#(Standard SQL)#

这没有任何作用。使用:

#StandardSQL

【讨论】:

谢谢。我不完全理解 1,2 和 3 在您的查询中代表什么。我只在示例中添加了#(Standard SQL)# 以说明我使用的是 StandardSQL,如果不清楚,请见谅。 @MC09 。 . .该查询只是标准 SQL 中接受该语法的演示。您的问题是查询被解释为旧版 SQL。【参考方案4】:

您好,根据文档,“(”具有特殊含义,因此请尝试不带括号。

SELECT * FROM Table_1 LEFT JOIN Table_2 ON Table_1.timestamp >= Table_2.TimeStampStart AND Table_1.timestamp <= Table_2.TimeStampEnd

Documentation here

【讨论】:

还是同样的错误信息。有没有其他方法可以在不使用 LEFT JOIN 的情况下实现相同的目标?

以上是关于标准 SQL:使用 BETWEEN 通过两个条件进行 LEFT JOIN的主要内容,如果未能解决你的问题,请参考以下文章

如何在同一列或不同列的一个sql语句中两次使用'BETWEEN'条件

通过索引优化sql

71《SQL学习指南(第二版)》between and

了解在 SQL 查询的自联接中使用“Between”条件时的逻辑查询处理

SQL:基于另一个表设置条件值,具有 BETWEEN 日期条件

如何在 SQL 的 WHERE CLAUSE 中的 CASE 内添加 sql“BETWEEN”条件