Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Cách chọn hàng đầu tiên trong mỗi nhóm theo nhóm

Vấn đề:

Bạn đã nhóm dữ liệu của mình với GROUP BY và chỉ muốn hiển thị hàng đầu tiên từ mỗi nhóm.

Ví dụ:

Cơ sở dữ liệu của chúng tôi có một bảng có tên exam_results với dữ liệu trong bảng sau:

first_name last_name năm kết quả
John Klein 2020 40
Edith Đen 2020 43
Đánh dấu Johnson 2019 32
Laura Mùa hè 2020 35
Kate Smith 2019 41
Jacob Đen 2019 44
Tom Bennett 2020 38
Emily Kelly 2020 43

Đối với mỗi năm, hãy tìm học sinh có result tốt nhất . Nếu có hai sinh viên được xếp vào hạng xuất sắc nhất trong một nhóm, chúng tôi sẽ tùy ý chọn một trong số họ để hiển thị.

Giải pháp:

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 1;

Kết quả là:

first_name last_name năm kết quả row_number
Jacob Đen 2019 44 1
Emily Kelly 2020 43 1

Thảo luận:

Đầu tiên, bạn cần viết một CTE trong đó bạn chỉ định một số cho mỗi hàng trong mỗi nhóm. Để làm điều đó, bạn có thể sử dụng ROW_NUMBER() hàm số. Trong OVER() , bạn chỉ định các nhóm mà các hàng sẽ được chia (PARTITION BY ) và thứ tự các số phải được gán cho các hàng (ORDER BY ).

Hãy xem kết quả của truy vấn bên trong:

SELECT
  *,
  ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
FROM exam_results;
first_name last_name năm kết quả row_number
Jacob Đen 2019 44 1
Kate Smith 2019 41 2
Đánh dấu Johnson 2019 32 3
Emily Kelly 2020 43 1
Edith Đen 2020 43 2
John Klein 2020 40 3
Tom Bennett 2020 38 4
Laura Mùa hè 2020 35 5

Bạn chỉ định số hàng trong mỗi nhóm (tức là năm). Mỗi hàng có một số hàng dựa trên giá trị của result cột. Các hàng được sắp xếp theo thứ tự giảm dần do DESC từ khóa sau ORDER BY result . Ngay cả khi có nhiều hàng trong một nhóm có cùng giá trị result , các hàng vẫn được cho các số khác nhau. Ở đây, Edith Black và Emily Kelly có cùng result nhưng số hàng khác nhau. Để thay đổi hành vi này và chỉ định cùng một số hàng cho cùng một kết quả trong một nhóm, hãy sử dụng RANK() hoặc DENSE_RANK() thay vì ROW_NUMBER() .

Trong truy vấn bên ngoài, bạn chọn tất cả dữ liệu từ CTE (added_row_number ) và sử dụng WHERE điều kiện để chỉ định hàng sẽ hiển thị từ mỗi nhóm. Ở đây, chúng tôi muốn hiển thị hàng đầu tiên, vì vậy điều kiện là row_number = 1 .

Lưu ý rằng bạn có thể dễ dàng sửa đổi giải pháp để lấy, ví dụ: hàng thứ hai của mỗi nhóm.

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 2;

Đây là kết quả:

first_name last_name năm kết quả row_number
Kate Smith 2019 41 2
Edith Đen 2020 43 2

Mặt khác, nếu bạn muốn nhận (các) hàng có giá trị cao thứ hai trong tổng số result trong mỗi nhóm, bạn nên sử dụng DENSE_RANK() hàm số. Trong khi ROW_NUMBER() hàm tạo các số liên tiếp cho mỗi hàng trong một nhóm, dẫn đến các giá trị khác nhau được gán cho các hàng có cùng kết quả, DENSE_RANK() hàm cung cấp cùng một số cho các hàng có cùng kết quả.

WITH added_dense_rank AS (
  SELECT
    *,
    DENSE_RANK() OVER(PARTITION BY year ORDER BY result DESC) AS rank
  FROM exam_results
)
SELECT
  *
FROM added_dense_rank
WHERE rank = 2;
first_name last_name năm kết quả xếp hạng
Kate Smith 2019 41 2
John Klein 2020 40 2

Bạn có thể thấy rằng John Klein có giá trị cao thứ hai của result (40) cho năm 2020. John Klein thực sự là người thứ ba trong nhóm, nhưng hai sinh viên đầu tiên có cùng result và cả hai đều có rank = 1 .


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thử thách đang diễn ra! Kêu gọi cộng đồng tạo trình tạo chuỗi số nhanh nhất

  2. Toán tử KHÔNG PHẢI của SQL

  3. Mặt nạ dữ liệu trong các ứng dụng DB

  4. Xem thông số, nhúng và các tùy chọn RECOMPILE

  5. Triển khai ứng dụng Django cho AWS Elastic Beanstalk