Para omitir a linha do resultado se alguma fonte linhas para o mesmo
id
tem value IS NULL
, uma solução no Postgres seria usar a função agregada every()
ou (sinônimo por motivos históricos) bool_and()
no 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);
SQL Fiddle.
Explicar
Sua tentativa com um
WHERE
cláusula apenas eliminaria um linha de origem para id = 3
no seu exemplo (aquele com colID = 1
), deixando mais dois para o mesmo id
. Então ainda temos uma linha para id = 3
no resultado após a agregação. Mas como não temos linha com
colID = 1
, obtemos uma string vazia (nota:não um NULL
valor!) para fn
no resultado para id = 3
. Uma solução mais rápida no Postgres seria usar
crosstab()
. Detalhes:Outros RDBMS
Enquanto
EVERY
é definido no padrão SQL:2008, muitos RDBMS não o suportam, presumivelmente porque alguns deles têm implementações obscuras do tipo booleano. (Não descartando nenhum nome como "MySQL" ou "Oracle" ...). Você provavelmente pode substituir em todos os lugares (incluindo Postgres) por: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()
não conta valores NULL. No MySQL também existe bit_and()
.Mais nesta questão relacionada: