這個查詢:BigQuery的標準SQL查詢返回一個錯誤的答案
SELECT x
FROM dataset.table_a
WHERE x NOT IN (SELECT x FROM dataset.table_b)
返回零記錄,即使:
場
x
在table_a
包含1326932不同的字符串值場
x
在table_b
中包含18,885個不同的字符串值
我不明白爲什麼。而且,在BigQuery遺留SQL中,此查詢返回正確的答案。
這個查詢:BigQuery的標準SQL查詢返回一個錯誤的答案
SELECT x
FROM dataset.table_a
WHERE x NOT IN (SELECT x FROM dataset.table_b)
返回零記錄,即使:
場x
在table_a
包含1326932不同的字符串值
場x
在table_b
中包含18,885個不同的字符串值
我不明白爲什麼。而且,在BigQuery遺留SQL中,此查詢返回正確的答案。
我懷疑我知道答案 - 這是由於NOT IN
在使用傳統SQL時與NULL
相關的錯誤處理,而標準SQL的行爲與SQL標準一致。有一個documentation bug open for this to add it to the migration guide,但它尚未解決。
在文檔(https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#in-operators)規定:
與在IN-list中的NULL只能返回TRUE或NULL,決不會爲假
可以實現與期望的行爲此查詢使用NOT EXISTS
代替:
SELECT x
FROM dataset.table_a AS t
WHERE NOT EXISTS (
SELECT 1 FROM dataset.table_b
WHERE t.x = x
);
謝謝你的回答。在我看來,這條規則似乎是這樣的: 「IN與NULL在IN列表中只能返回TRUE或NULL,從不FALSE」 是邏輯錯誤,是不是?例如,'aa'IN ['bb',NULL]在邏輯上應該返回FALSE? – gus87
它等同於'aa'='bb'或'aa'= NULL,這會導致NULL。試試這個:'SELECT'aa'='bb'或'aa'=(SELECT CAST(NULL as STRING))'。 –
要最小化原始查詢中的更改,您可以只添加WHERE NOT x IS NULL
如下
#standardSQL
SELECT x
FROM `dataset.table_a`
WHERE x NOT IN (SELECT x FROM `dataset.table_b` WHERE NOT x IS NULL)
另外,我建議增加DISTINCT如下優化了一點
#standardSQL
SELECT x
FROM `dataset.table_a`
WHERE x NOT IN (SELECT DISTINCT x FROM `dataset.table_b` WHERE NOT x IS NULL)
你可以給數據的例子嗎?它是否填充?如果您將NOT IN更改爲IN,您會得到什麼結果? –
遷移指南現在已更新爲[記錄傳統和標準SQL之間的區別](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#not_in_conditions_and_null) 。 –