Để bỏ qua hàng khỏi kết quả nếu có trong nguồn các hàng cho cùng một id
có giá trị value IS NULL
, một giải pháp trong Postgres sẽ sử dụng hàm tổng hợp every()
hoặc (từ đồng nghĩa với lý do lịch sử) bool_and()
trong HAVING
mệnh đề:
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);
Giải thích
Nỗ lực của bạn với WHERE
mệnh đề sẽ chỉ loại bỏ một hàng nguồn cho id = 3
trong ví dụ của bạn (ví dụ có colID = 1
), để lại hai cái nữa cho cùng một id
. Vì vậy, chúng tôi vẫn nhận được một hàng cho id = 3
trong kết quả sau khi tổng hợp.
Nhưng vì chúng ta không có hàng nào có colID = 1
, chúng tôi nhận được một chuỗi trống (lưu ý:không phải là NULL
value!) cho fn
trong kết quả cho id = 3
.
Một giải pháp nhanh hơn trong Postgres sẽ là sử dụng crosstab()
. Chi tiết:
RDBMS khác
Trong khi EVERY
được định nghĩa trong tiêu chuẩn SQL:2008, nhiều RDBMS không hỗ trợ nó, có lẽ là do một số trong số chúng có triển khai kiểu boolean mờ ám. (Không bỏ bất kỳ tên nào như "MySQL" hoặc "Oracle" ...). Bạn có thể thay thế ở mọi nơi (kể cả Postgres) bằng:
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);
Vì count()
không tính giá trị NULL. Trong MySQL cũng có bit_and()
.Xem thêm dưới câu hỏi liên quan này: