За да пропуснете реда от резултата ако някой от източника редове за един и същи id
има value IS NULL
, решение в Postgres би било да се използва агрегатната функция every()
или (синоним по исторически причини) bool_and()
в HAVING
клауза:
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);
Обяснете
Вашият опит с WHERE
клауза просто ще елиминира един изходен ред за id = 3
във вашия пример (този с colID = 1
), оставяйки още две за същия id
. Така че все още получаваме ред за id = 3
в резултата след агрегиране.
Но тъй като нямаме ред с colID = 1
, получаваме празен низ (забележка:не NULL
стойност!) за fn
в резултата за id = 3
.
По-бързо решение в Postgres би било използването на crosstab()
. Подробности:
Други RDBMS
Докато EVERY
е дефиниран в стандарта SQL:2008, много RDBMS не го поддържат, вероятно защото някои от тях имат сенчести реализации на булев тип. (Без изпускане на имена като "MySQL" или "Oracle" ...). Вероятно можете да замените навсякъде (включително Postgres) с:
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);
Тъй като count()
не отчита NULL стойности. В MySQL също има bit_and()
.Още под този свързан въпрос: