Para omitir la fila del resultado si alguna de las fuente filas para el mismo id
tiene value IS NULL
, una solución en Postgres sería usar la función agregada every()
o (sinónimo por razones históricas) bool_and()
en el HAVING
cláusula:
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);
Explicar
Tu intento con un WHERE
cláusula simplemente eliminaría uno fila de origen para id = 3
en su ejemplo (el que tiene colID = 1
), dejando dos más para el mismo id
. Entonces todavía obtenemos una fila para id = 3
en el resultado después de agregar.
Pero como no tenemos una fila con colID = 1
, obtenemos una cadena vacía (nota:no un NULL
valor!) para fn
en el resultado de id = 3
.
Una solución más rápida en Postgres sería usar crosstab()
. Detalles:
Otro RDBMS
Mientras que EVERY
está definido en el estándar SQL:2008, muchos RDBMS no lo admiten, presumiblemente porque algunos de ellos tienen implementaciones dudosas del tipo booleano. (Sin soltar ningún nombre como "MySQL" u "Oracle"...). Probablemente pueda sustituirlo en todas partes (incluido Postgres) con:
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);
Porque count()
no cuenta valores NULL. En MySQL también hay bit_and()
.Más en esta pregunta relacionada: