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: