Pour omettre la ligne du résultat si l'une des sources lignes pour le même id
a value IS NULL
, une solution en Postgres serait d'utiliser la fonction d'agrégation every()
ou (synonyme pour des raisons historiques) bool_and()
dans le HAVING
clause :
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING every(value IS NOT NULL);
Expliquez
Votre tentative avec un WHERE
la clause en éliminerait simplement une ligne source pour id = 3
dans votre exemple (celui avec colID = 1
), en laissant deux autres pour le même id
. Nous obtenons donc toujours une ligne pour id = 3
dans le résultat après agrégation.
Mais puisque nous n'avons pas de ligne avec colID = 1
, nous obtenons une chaîne vide (note :pas un NULL
valeur !) pour fn
dans le résultat pour id = 3
.
Une solution plus rapide dans Postgres serait d'utiliser crosstab()
. Détails :
Autre SGBDR
Tandis que EVERY
est défini dans la norme SQL:2008, de nombreux SGBDR ne le prennent pas en charge, probablement parce que certains d'entre eux ont des implémentations douteuses du type booléen. (Ne supprimez aucun nom comme "MySQL" ou "Oracle" ...). Vous pouvez probablement remplacer partout (y compris Postgres) par :
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING count(*) = count(value);
Parce que count()
ne compte pas les valeurs NULL. Dans MySQL, il y a aussi bit_and()
.Plus d'informations sous cette question connexe :