2017-05-04 8 views
4

Diese Abfrage:BigQuery Standard-SQL-Abfrage gibt eine falsche Antwort

SELECT x 
FROM dataset.table_a 
WHERE x NOT IN (SELECT x FROM dataset.table_b) 

Null zurückgibt Datensätze obwohl:

  • Feld x in table_a 1.326.932 verschiedene String

  • Feldwerte enthält x in table_b enthält 18.885 verschiedene Zeichenfolgenwerte

Ich verstehe nicht warum. Darüber hinaus gibt diese Abfrage in BigQuery-Legacy-SQL die richtige Antwort zurück.

+0

Können Sie ein Beispiel der Daten geben zu optimieren? Ist es gepolstert? Wenn du NICHT IN zu IN änderst, was bekommst du für ein Ergebnis? –

+0

Der Migrationsleitfaden wurde jetzt aktualisiert auf [dokumentieren Sie den Unterschied zwischen Legacy- und Standard-SQL] (https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#not_in_conditions_and_null). . –

Antwort

3

Ich vermute, dass ich die Antwort kenne - es ist aufgrund der inkorrekten Handhabung von NULL in Bezug auf NOT IN bei der Verwendung von Legacy SQL, während das Verhalten mit Standard-SQL mit dem SQL-Standard übereinstimmt. Es gibt eine documentation bug open for this to add it to the migration guide, aber es wurde noch nicht gelöst.

Die Dokumentation für IN (https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#in-operators) heißt es:

IN mit einem NULL in der IN-Liste nur TRUE oder NULL zurückgeben kann, FALSCH nie

Sie das gewünschte Verhalten mit erreichen kann diese Abfrage mit NOT EXISTS statt:

SELECT x 
FROM dataset.table_a AS t 
WHERE NOT EXISTS (
    SELECT 1 FROM dataset.table_b 
    WHERE t.x = x 
); 
+0

Vielen Dank für Ihre Antwort. Meiner Meinung nach scheint diese Regel: "IN mit einem NULL in der IN-Liste kann nur TRUE oder NULL, nie FALSE" ist logisch falsch, nicht wahr? Zum Beispiel sollte 'aa' IN ['bb', NULL] logisch FALSE zurückgeben? – gus87

+0

Dies entspricht "aa" = "bb" ODER "aa" = NULL, was zu NULL führt. Probieren Sie dies aus: 'SELECT 'aa' = 'bb' ODER 'aa' = (SELECT CAST (NULL AS STRING))'. –

3

Um Änderungen in Ihrem originalquery zu minimieren können Sie einfach hinzufügen WHERE NOT x IS NULL wie unten

#standardSQL 
SELECT x 
FROM `dataset.table_a` 
WHERE x NOT IN (SELECT x FROM `dataset.table_b` WHERE NOT x IS NULL) 

Auch empfehle ich das Hinzufügen wie unten DISTINCT es ein wenig

#standardSQL 
SELECT x 
FROM `dataset.table_a` 
WHERE x NOT IN (SELECT DISTINCT x FROM `dataset.table_b` WHERE NOT x IS NULL) 
Verwandte Themen