web-dev-qa-db-fra.com

Puis-je fournir une valeur par défaut pour une jointure externe gauche?

Supposons que j'ai les tables a (avec la colonne a1) et b (avec les colonnes b1 et b2) et que j'effectue une jointure externe gauche

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

Alors b1 et b2 seront NULL où une valeur de a1 n'a pas de valeur correspondante de b1.

Puis-je fournir une valeur par défaut pour b2, au lieu de NULL? Notez que COALESCE ne fonctionnera pas ici, car je ne pas veut que la valeur par défaut remplace les NULL potentiels dans b2 où est une valeur de b1 correspondant à a1.

Autrement dit, avec a et b comme

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

et une valeur par défaut pour b2 de, disons 100, je veux obtenir le résultat

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

Dans ce cas simple, je pourrais le faire "à la main" en regardant si b1 est NULL dans la sortie. Est-ce la meilleure option en général, ou existe-t-il une manière plus standard et plus soignée?

22
Tom Ellis
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
25
Mordechai

Je trouve COALESCE très utile dans ce cas. Il renverra la première valeur non NULL d'une liste:

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

La réponse originale à cette question est restée inexpliquée, alors donnons-en un autre coup.

Utilisation d'une instruction CASE

En utilisant cette méthode, nous exploitons cela nous avons une autre valeur dans une colonne différente qui IS NOT NULL dans ce cas b.b1 si cette valeur est nulle, nous savons que la jointure a échoué.

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

Cela fonctionnera totalement et générera exactement ce que vous voulez.

Utilisation d'un sous-SELECT

N'utilisez pas cette méthode, c'est une idée d'accumulation. Continuez à lire.

Si nous n'avons pas de NOT NULL colonnes que nous pouvons exploiter comme ça, nous avons besoin de quelque chose pour créer une colonne qui puisse fonctionner de cette façon pour nous ...

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

Utilisation d'une comparaison de lignes

Il est encore plus facile de forcer une valeur fausse pour laquelle nous pouvons comparer, c'est de comparer la ligne. Dans PostgreSQL, la ligne a une valeur par le nom de la table. Par exemple, SELECT foo FROM foo renvoie une ligne de type foo (qui est un type de ligne), à ​​partir de la table foo. Ici, nous testons pour voir si cette ROW est nulle. Cela fonctionnera tant que chaque colonne IS NOT NULL. Et, si chaque colonne IS NULL dans votre table, alors vous êtes juste à la traîne.

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);
2
Evan Carroll