如果其中一个键为空,则BigQuery中的多个键上的左外连接不会出现

时间:2015-07-10 02:06:47

标签: google-bigquery

我在BigQuery的多个键上遇到了一些奇怪的左外连接。如果其中一个键位于右表的null,则它不匹配,因此会将null放入右表的所有值中。

如果我有2张桌子

   Table1              Table2
------------      ----------------
 k1 |k2  |v3      k1 |k2  | v4
------------      ----------------
 foo|boo |hey     foo|NULL| you
 bar|test|yo      bar|test| hi
 foo|NULL|hey

我做以下连接

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上没有匹配。

有没有其他方法可以产生我想要的结果?

2 个答案:

答案 0 :(得分:8)

在SQL中,NULL不等于任何东西 - 甚至本身。

Gordon's answer有一些合理的建议,但请注意,BigQuery仅支持连接条件,这些条件是均衡的连接,排除使用ORIS NULL

你能使用除null之外的sentinel值吗?例如,如果您将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"时,这才有效。

答案 1 :(得分:1)

这是标准行为。修复它的一种方法是使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键,这很难组合在一起。