2015-07-10 12 views
6

Ich stieß auf etwas seltsam mit linken äußeren Joins auf mehreren Schlüsseln in BigQuery. Wenn einer der Schlüssel auf der rechten Tabelle null ist, stimmt er nicht überein und setzt daher null in alle Werte für die richtige Tabelle.Links äußerer Join in BigQuery auf mehreren Schlüsseln nicht, wenn einer von ihnen null ist

Wenn ich habe 2 Tabellen

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

und ich die folgende beitreten

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 

ich ein Ergebnis wie dieses

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. 

ich, dass das letzte erwarten Reihe war

foo |NULL |hey |you 

Ist das das erwartete Verhalten? Damit meine ich keine Treffer auf NULL.

Gibt es eine andere Möglichkeit, das gewünschte Ergebnis zu erzielen?

+0

Einige andere SQL-Anweisungen haben "IS NICHT DISTINCT FROM", aber BigQuery hat sie nicht. Weitere Informationen finden Sie unter "Wie neu zu schreiben IS DISTINCT FROM und nicht von DISTINCT FROM?" http://stackoverflow.com/questions/10416789/how-to-rewrite-is-distinct-from-and-is-not-distinct-from –

Antwort

6

In SQL, NULL ist nichts gleich - auch sich selbst.

Gordon's answer hat einige vernünftige Vorschläge, aber beachten Sie, dass BigQuery unterstützt nur Bedingungen beitreten, die Konjunktionen von Gleichheiten sind, die Verwendung von OR oder IS NULL ausschließt.

Können Sie einen anderen Sentinel-Wert als null verwenden? Wenn Sie beispielsweise NULL durch die leere Zeichenfolge (oder die Zeichenfolge "null" oder etwas anderes ersetzen, das an keiner anderen Stelle in Ihren Daten vorkommt), funktioniert die Verknüpfung wie erwartet. Sie können dies sogar im Handumdrehen tun, indem Sie eine Unterabfrage zu minimalen Leistungskosten verwenden.

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 

Sie können eine äußere wählen fügen Sie die Zeichenfolge "null" zurück in eine echte NULL zu drehen.

Offensichtlich funktioniert dies nur, wenn die Zeichenfolge "null" nicht an anderer Stelle in Ihren Daten auftritt.

1

Dies ist Standardverhalten. Eine Methode, um es zu beheben ist, um die join Klausel komplizierter:

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)) 

dies eine schlechte Auswirkung auf die Leistung haben. Einige Datenbanken haben eine null-sichere Gleichheitsoperation, die verwendet werden kann, aber ich denke nicht, dass BigQuery dies unterstützt.

Also, der beste Rat ist, die Daten zu beheben, so NULL ist kein gültiger Schlüsselwert. Andernfalls können Sie mehrere Joins verwenden. Wenn Sie nur einen join Schlüssel hatte, würde es aussehen

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) ; 

Dies ist jedoch schwieriger zusammen zu stellen für Verbund join Tasten.

Verwandte Themen