如果其中一个为空,则 BigQuery 中多个键的左外连接不会
Left outer join in BigQuery on multiple keys doesn't if one of them is null
我 运行 对 BigQuery 中多个键的左外连接感到奇怪。如果其中一个键是右侧 table 上的 null
,则它不匹配,因此它将 null
放入右侧 table.
的所有值中
如果我有 2 tables
Table1 Table2
------------ ----------------
k1 |k2 |v3 k1 |k2 | v4
------------ ----------------
foo|boo |hey foo|NULL| you
bar|test|yo bar|test| hi
foo|NULL|hey
然后我执行以下操作 join
SELECT t1.k1, t1.k2, t1.v3, t2.v4 FROM [Table1] t1
LEFT OUTER JOIN EACH [Table2] t2
ON t1.k1=t2.k1 AND t1.k2=t2.k2
我得到这样的结果
t1_k1|t1_k2|t1_v3|t2_v4
-----------------------
foo |boo |hey |NULL --No match here so NULL in t2_v4 it's ok
bar |test |hey |hi --It matches here on bar and test
foo |NULL |hey |NULL --It doesn't match on foo NULL.
我希望最后一行是
foo |NULL |hey |you
这是预期的行为吗?我的意思是 NULL
.
上没有匹配项
还有其他方法可以得到我想要的结果吗?
这是标准行为。修复它的一种方法是使 join
子句更复杂:
SELECT t1.k1, t1.k2, t1.v3, t2.v4
FROM [Table1] t1 LEFT OUTER JOIN EACH
[Table2] t2
ON (t1.k1 = t2.k1 OR (t1.k1 is null and t2.k1 is null)) AND
(t1.k2 = t2.k2 OR (t1.k2 is null and t2.k2 is null))
这可能会对性能产生不良影响。一些数据库有空安全的相等操作可以使用,但我认为 BigQuery 不支持。
因此,最好的建议是修复数据,使 NULL
不是有效的键值。否则,您可以使用多个连接。如果你只有一个 join
键,它看起来像
SELECT t1.k1, t1.k2, t1.v3, coalesce(t2.v4, t2null.v4)
FROM [Table1] t1 LEFT OUTER JOIN EACH
[Table2] t2
ON t1.k1 = t2.k1 LEFT OUTER JOIN EACH
[Table2] t2null
ON (t1.k1 is null and t2.k1 is null) ;
但是,对于复合 join
键,这更难组合在一起。
在 SQL 中,NULL
不等于任何东西——甚至它本身。
有一些合理的建议,但请注意,BigQuery 仅支持等式连接的连接条件,这排除了 OR
或 IS NULL
.[=20= 的使用]
能否使用空值以外的标记值?例如,如果您将 NULL
替换为空字符串(或字符串 "null"
,或数据中其他地方未出现的其他内容),连接将按您预期的那样工作。您甚至可以使用子查询以最低的性能成本即时执行此操作。
SELECT t1.k1, t1.k2, t1.v3, t2.v4
FROM
(SELECT IFNULL(k1, "null") k1, IFNULL(k2, "null") k2 FROM [Table1]) t1
LEFT OUTER JOIN EACH
(SELECT IFNULL(v3, "null") v3, IFNULL(v4, "null") v4 FROM [Table2]) t2
ON t1.k1 = t2.k1 AND t1.k2 = t2.k2
您可以添加一个外部 select 将字符串 "null"
变回真正的 NULL
。
显然,只有当字符串 "null"
没有出现在您的数据的其他地方时,这才有效。
我 运行 对 BigQuery 中多个键的左外连接感到奇怪。如果其中一个键是右侧 table 上的 null
,则它不匹配,因此它将 null
放入右侧 table.
如果我有 2 tables
Table1 Table2
------------ ----------------
k1 |k2 |v3 k1 |k2 | v4
------------ ----------------
foo|boo |hey foo|NULL| you
bar|test|yo bar|test| hi
foo|NULL|hey
然后我执行以下操作 join
SELECT t1.k1, t1.k2, t1.v3, t2.v4 FROM [Table1] t1
LEFT OUTER JOIN EACH [Table2] t2
ON t1.k1=t2.k1 AND t1.k2=t2.k2
我得到这样的结果
t1_k1|t1_k2|t1_v3|t2_v4
-----------------------
foo |boo |hey |NULL --No match here so NULL in t2_v4 it's ok
bar |test |hey |hi --It matches here on bar and test
foo |NULL |hey |NULL --It doesn't match on foo NULL.
我希望最后一行是
foo |NULL |hey |you
这是预期的行为吗?我的意思是 NULL
.
还有其他方法可以得到我想要的结果吗?
这是标准行为。修复它的一种方法是使 join
子句更复杂:
SELECT t1.k1, t1.k2, t1.v3, t2.v4
FROM [Table1] t1 LEFT OUTER JOIN EACH
[Table2] t2
ON (t1.k1 = t2.k1 OR (t1.k1 is null and t2.k1 is null)) AND
(t1.k2 = t2.k2 OR (t1.k2 is null and t2.k2 is null))
这可能会对性能产生不良影响。一些数据库有空安全的相等操作可以使用,但我认为 BigQuery 不支持。
因此,最好的建议是修复数据,使 NULL
不是有效的键值。否则,您可以使用多个连接。如果你只有一个 join
键,它看起来像
SELECT t1.k1, t1.k2, t1.v3, coalesce(t2.v4, t2null.v4)
FROM [Table1] t1 LEFT OUTER JOIN EACH
[Table2] t2
ON t1.k1 = t2.k1 LEFT OUTER JOIN EACH
[Table2] t2null
ON (t1.k1 is null and t2.k1 is null) ;
但是,对于复合 join
键,这更难组合在一起。
在 SQL 中,NULL
不等于任何东西——甚至它本身。
能否使用空值以外的标记值?例如,如果您将 您可以添加一个外部 select 将字符串 显然,只有当字符串 OR
或 IS NULL
.[=20= 的使用]
NULL
替换为空字符串(或字符串 "null"
,或数据中其他地方未出现的其他内容),连接将按您预期的那样工作。您甚至可以使用子查询以最低的性能成本即时执行此操作。SELECT t1.k1, t1.k2, t1.v3, t2.v4
FROM
(SELECT IFNULL(k1, "null") k1, IFNULL(k2, "null") k2 FROM [Table1]) t1
LEFT OUTER JOIN EACH
(SELECT IFNULL(v3, "null") v3, IFNULL(v4, "null") v4 FROM [Table2]) t2
ON t1.k1 = t2.k1 AND t1.k2 = t2.k2
"null"
变回真正的 NULL
。"null"
没有出现在您的数据的其他地方时,这才有效。