Kann ich einen Standardwert für eine linke äußere Verknüpfung angeben?

21

Angenommen, ich habe Tabellen a (mit Spalte a1) und b (mit Spalten b1 und b2) und führe einen Left Outer Join durch

SELECT *
FROM a LEFT OUTER JOIN b
ON a.a1 = b.b1

Dann werden b1 und b2 NULL sein, wobei ein Wert von a1 keinen übereinstimmenden Wert von b1 hat.

Kann ich einen Standardwert für b2 anstelle von NULL angeben? Beachten Sie, dass COALESCE funktioniert hier nicht, weil ich nicht den Standardwert Potential NULLs in b2 außer Kraft setzen möchten , wo es ist ein Wert von b1 Anpassung a1.

Das heißt, mit a und b als

CREATE TABLE a (a1)
  AS VALUES (1),
            (2),
            (3) ;

CREATE TABLE b (b1,b2)
  AS VALUES (1, 10),
            (3, null) ;


a1     b1 | b2
---    --------
 1      1 | 10
 2      3 | NULL
 3

und eine Standardeinstellung für b2 von beispielsweise 100, möchte ich das Ergebnis erhalten

a1 | b1   | b2
---------------
1  |  1   | 10
2  | NULL | 100
3  |  3   | NULL

In diesem einfachen Fall könnte ich es "von Hand" tun, indem ich prüfe, ob b1 in der Ausgabe NULL ist. Ist das die beste Option im Allgemeinen, oder gibt es eine normalere und ordentlichere Möglichkeit?

Tom Ellis
quelle

Antworten:

23
SELECT a.a1,b.b1,  
    CASE WHEN b.b1 is NULL THEN 5 ELSE b.b2 END AS b2  
FROM a LEFT OUTER JOIN b  
ON a.a1 = b.b1
Mordechai
quelle
2
Bitte verwenden Sie ANSI SQL, wenn die Frage nur mit einem Tag versehen ist sql(was "SQL als Abfragesprache" bedeutet. Dieses Tag kennzeichnet kein bestimmtes DBMS-Produkt oder keinen bestimmten Dialekt). Der Teil: [b2]=CASE WHEN ... ENDist ein ungültiger (Standard-) SQL-Ausdruck.
a_horse_with_no_name
Ich habe ein Tag hinzugefügt, um anzuzeigen, dass ich eine Postgres-spezifische Antwort akzeptieren würde. Trotzdem wäre Standard-SQL nach Möglichkeit vorzuziehen.
Tom Ellis
@Kin: Wie in meiner Frage angegeben, weiß ich, dass ich es "von Hand" tun kann, indem ich prüfe, ob b1 in der Ausgabe NULL ist.
Tom Ellis
3
Da Sie zwischen NULL-Werten unterscheiden möchten, die aufgrund eines JOIN-Werts auftreten, und solchen, die "natürlich" vorhanden sind, ist es unvermeidlich, dass Sie b1 untersuchen müssen. Wenn Sie das mit "Ich könnte es" von Hand "gemeint haben, dann ist das der einzige Weg.
Mordechai
@MorDeror: OK, ich denke, es könnte eine Syntax wie "LEFT OUTER JOIN ... ON ... DEFAULT b2 = ..." geben.
Tom Ellis
2

Die ursprüngliche Antwort auf diese Frage blieb ungeklärt.

Mit einer CASEAussage

Bei Verwendung dieser Methode wird ausgenutzt, dass in einer anderen Spalte ein andererIS NOT NULLb.b1 Wert vorhanden ist. Wenn dieser Wert in diesem Fall null ist, wissen wir, dass der Join fehlgeschlagen ist.

SELECT
  a.a1,
  b.b1,  
  CASE WHEN b.b1 is NULL THEN 100 ELSE b.b2 END AS b2  
FROM a
LEFT OUTER JOIN b  
  ON (a.a1 = b.b1);

Dies wird vollkommen funktionieren und genau das erzeugen, was Sie wollen.

Unterauswahl verwenden

Wenden Sie diese Methode nicht an, sie ist eine Idee für den Aufbau. Weiter lesen.

Wenn wir keine NOT NULLSpalten haben , die wir so ausnutzen können, brauchen wir etwas, um eine Spalte zu erstellen, die für uns so funktionieren kann ...

SELECT
  a.a1,
  b.b1,  
  CASE WHEN b.cond IS NULL THEN 100 ELSE b.b2 END AS b2  
FROM a
LEFT OUTER JOIN (
  SELECT true AS cond, b.*
  FROM b
) AS b
  ON (a.a1 = b.b1);

Verwenden eines Zeilenvergleichs

Noch einfacher, als einen falschen Wert zu erzwingen, für den wir vergleichen können, ist es, die Zeile zu vergleichen. In PostgreSQL hat die Zeile einen Wert nach dem Namen der Tabelle. Gibt beispielsweise SELECT foo FROM fooeine Zeile vom Typ foo(ein Zeilentyp) aus der Tabelle zurück foo. Hier testen wir, ob diese Zeile null ist. Dies funktioniert so lange wie jede Spalte IS NOT NULL. Und wenn jede Spalte IS NULLin Ihrer Tabelle, dann trollen Sie nur.

SELECT
  a.a1,
  b.b1,  
  CASE WHEN b IS NULL THEN 100 ELSE b.b2 END AS b2  
FROM a
LEFT OUTER JOIN b
  ON (a.a1 = b.b1);
Evan Carroll
quelle
Die b1in der CASELösung verwendete Spalte muss nicht nullwertfähig sein. Die Bauarbeiten in beiden Fällen.
ypercubeᵀᴹ 20.03.17
1

Ich finde COALESCE in diesem Fall sehr nützlich. Es wird der erste Nicht-NULL-Wert aus einer Liste zurückgegeben:

SELECT
 a.a1,
 b.b1,
 COALESCE (b.b2, 100) AS b2
FROM a
LEFT OUTER JOIN b
  ON (a.a1 = b.b1);
rauben
quelle