Trả về số lượng cho nhiều phạm vi trong một câu lệnh CHỌN


9

Tôi có một bảng cơ sở dữ liệu Postgres foo, trong số những thứ khác, có một cột cho scorephạm vi từ 0 - 10. Tôi muốn một truy vấn trả về tổng số điểm, số điểm từ 0 đến 3, số điểm từ 4 và 6, và số điểm từ 7 đến 10. Một số thứ như sau:

SELECT
  COUNT(*) as total,
  COUNT(
    SELECT * from foo where score between 0 and 3;
  ) as low,
  COUNT(
    SELECT * from foo where score between 4 and 6;
  ) as mid,
  COUNT(
    SELECT * from foo where score between 7 and 10;
  ) as high
FROM foo;

Tôi đã thử điều này, nhưng đã gặp lỗi với SELECTcác COUNTbáo cáo. Bất kỳ ý tưởng làm thế nào tôi có thể làm điều này? Tôi chắc chắn có một cách siêu đơn giản trong Postgres. Tôi chỉ không thể tìm ra các điều khoản chính xác cho Google cho.

Câu trả lời:


7

Chỉ cần sử dụng các SUM()câu điều kiện trên mỗi cột cho mỗi phạm vi số. Tổng số có thể được tổng hợp bằng cách chỉ sử dụng SUM(1), giả sử tất cả dữ liệu trong bảng nằm trong một trong các phạm vi - nếu không, chỉ cần hạn chế nó như với các dữ liệu khác.

select sum(case when score between 0 and 3 then 1 else 0 end) as minrange,
       sum(case when score between 4 and 6 then 1 else 0 end) as midrange,
       sum(case when score between 7 and 10 then 1 else 0 end) as maxrange,
       sum(1) as total
from foo;

Liên kết Fiddle SQL .


8

FILTERMệnh đề tổng hợp trong Postgres 9.4+

Vì Postgres 9.4, có một cách nhanh chóng và nhanh chóng (tiêu chuẩn SQL):

SELECT count(*) FILTER (WHERE score BETWEEN 0 AND 3)  AS low
     , count(*) FILTER (WHERE score BETWEEN 4 AND 7)  AS mid
     , count(*) FILTER (WHERE score BETWEEN 8 AND 10) AS high
     , count(*)                                       AS total
FROM   foo;

totalcộng lại low, midhigh, trừ khi NULL hoặc các giá trị khác có liên quan.

Liên kết:

Cũng đọc dưới đây.

Hậu 9,3-

Có một vài kỹ thuật:

@Phil cung cấp cách tiêu chuẩn với một CASEtuyên bố (ngoại trừ sum(1), đó không phải là cách tiêu chuẩn). Tôi thích sử dụng một hình thức ngắn hơn:

SELECT count(score BETWEEN 0 AND 3  OR NULL) AS low
     , count(score BETWEEN 4 AND 6  OR NULL) AS mid
     , count(score BETWEEN 7 AND 10 OR NULL) AS high
     , count(*)                              AS total
FROM   foo;

Nếu các giá trị của bạn như được xác định trong câu hỏi của bạn (chỉ 0- 10có thể), hãy đơn giản hóa hơn nữa:

SELECT count(score < 4 OR NULL)             AS low
     , count(score BETWEEN 4 AND 6 OR NULL) AS mid
     , count(score > 6 OR NULL)             AS high
     , count(*)                             AS total
FROM   foo;

Ngắn hơn một chút, nhanh hơn

Sự khác biệt tinh tế

khác biệt tinh tế khi so sánh với sum()trong câu trả lời của Phil :

  • Quan trọng nhất, mỗi tài liệu :

    Cần lưu ý rằng ngoại trừ count, các hàm này trả về giá trị null khi không có hàng nào được chọn. Cụ thể, sumkhông có hàng nào trả về null, không phải bằng 0 như người ta mong đợi, ...

  • count(*) cách tiêu chuẩn và nhanh hơn một chút sum(1). Một lần nữa, null so với 0 áp dụng.

Một trong hai truy vấn này (bao gồm cả Phil) đều tính các giá trị null cho total. Nếu đó là điều không mong muốn, hãy sử dụng thay thế:

count(score) AS total_not_null

Câu đố SQL trong trang 9.3.
db <> fiddle ở đây trong pg 10.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.