For at udelade rækken fra resultatet hvis nogen af kilden rækker for det samme id
har value IS NULL
, en løsning i Postgres ville være at bruge den samlede funktion every()
eller (synonym af historiske årsager) bool_and()
i HAVING
klausul:
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);
Forklar
Dit forsøg med en WHERE
klausul ville bare fjerne én kilderække for id = 3
i dit eksempel (den med colID = 1
), efterlader to mere for det samme id
. Så vi får stadig en række for id = 3
i resultatet efter sammenlægning.
Men da vi ikke har nogen række med colID = 1
, får vi en tom streng (bemærk:ikke en NULL
værdi!) for fn
i resultatet for id = 3
.
En hurtigere løsning i Postgres ville være at bruge crosstab()
. Detaljer:
Andre RDBMS
Mens EVERY
er defineret i SQL:2008-standarden, understøtter mange RDBMS det ikke, formentlig fordi nogle af dem har lyssky implementeringer af den booleske type. (Slet ikke navne som "MySQL" eller "Oracle" ...). Du kan sikkert erstatte alle steder (inklusive Postgres) med:
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);
Fordi count()
tæller ikke NULL-værdier. I MySQL er der også bit_and()
.Mere under dette relaterede spørgsmål: