Aby pominąć wiersz w wyniku jeśli którykolwiek z źródła wiersze dla tego samego id ma value IS NULL , rozwiązanie w Postgresie byłoby użycie funkcji agregującej every()
lub (synonim ze względów historycznych) bool_and()
w HAVING klauzula:
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); Wyjaśnij
Twoja próba z WHERE klauzula po prostu wyeliminuje jeden wiersz źródłowy dla id = 3 w twoim przykładzie (ten z colID = 1 ), pozostawiając jeszcze dwa dla tego samego id . Więc nadal otrzymujemy wiersz dla id = 3 w wyniku po agregacji.
Ale ponieważ nie mamy wiersza z colID = 1 , otrzymujemy pusty ciąg (uwaga:nie NULL wartość!) dla fn w wyniku dla id = 3 .
Szybszym rozwiązaniem w Postgresie byłoby użycie crosstab() . Szczegóły:
Inne RDBMS
Podczas gdy EVERY jest zdefiniowany w standardzie SQL:2008, wiele RDBMS go nie obsługuje, prawdopodobnie dlatego, że niektóre z nich mają podejrzane implementacje typu logicznego. (Nie upuszczaj żadnych nazw, takich jak "MySQL" lub "Oracle" ...). Prawdopodobnie możesz zastąpić wszędzie (w tym Postgres) za pomocą:
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);
Ponieważ count() nie liczy wartości NULL. W MySQL istnieje również bit_and()
.Więcej pod tym pytaniem: