Điều này không tầm thường. Đầu tiên, bạn muốn nhóm theo id và tên và đếm các hàng:
SELECT COUNT(*)
...
GROUP BY id, name
Sau đó chọn số lượng tối đa cho mỗi id. Một cách để đạt được điều này là bằng các chức năng của cửa sổ. Các RANK()
chức năng:
RANK() OVER (PARTITION BY id ORDER BY COUNT(*) DESC)
gán một số cho mỗi hàng của kết quả (sau khi hoàn thành việc phân nhóm), sắp xếp chúng (các hàng) trong các phân vùng giống nhau id
và được sắp xếp theo COUNT(*) DESC
, vì vậy với mỗi (phân vùng) id
, các hàng có số lượng tối đa là được chỉ định một cấp bậc 1. Do đó, chúng ta cần đặt ở trên trong một bảng dẫn xuất và sử dụng một WHERE
điều kiện để chỉ giữ các hàng này:
WHERE rnk = 1
Truy vấn cuối cùng là như thế này:
SELECT
id, name, cnt
FROM
( SELECT id, name, COUNT(*) AS cnt,
RANK() OVER (PARTITION BY id ORDER BY COUNT(*) DESC) AS rnk
FROM tableX
GROUP BY id, name
) AS tg
WHERE
rnk = 1 ;
Đã thử nghiệm tại SQL-Fiddle
Lưu ý rằng nếu bạn có quan hệ ở vị trí đầu tiên (hai hoặc nhiều tên có cùng số lượng tối đa), tất cả những tên này sẽ được trả về. Nếu bạn muốn đúng một hàng cho mỗi id trong kết quả cuối cùng, bạn phải sử dụng ROW_NUMBER()
thay vì RANK()
và có thể thay đổi ORDER BY
mệnh đề để chọn rõ ràng cách giải quyết các mối quan hệ:
ROW_NUMBER() OVER (PARTITION BY id ORDER BY COUNT(*) DESC, name ASC) AS rnk
Đã kiểm tra: SQL-Fiddle test-2 .
max
sẽ tìm thấy tên sắp xếp theo từ vựng, không phải là tên được tích lũy nhiều lần nhất. Bạn thực sự muốn mộtmode
tổng hợp (theo nghĩa thống kê) cho điều đó, và tôi không nghĩ rằng một cái được cung cấp. Ai đó đã viết một cái trên wiki, nhưng tôi nghi ngờ nó rất hiệu quả. Hãy dùng thử: wiki.postgresql.org/wiki/Aggregate_Mode và scottrbailey.wordpress.com/2009/05/22/ Kẻ