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

Làm thế nào để CHỌN bốn mục mới nhất cho mỗi danh mục?

Đây là vấn đề lớn nhất-n-per-group và là một câu hỏi SQL rất phổ biến.

Đây là cách tôi giải quyết nó với các phép nối bên ngoài:

SELECT i1.*
FROM item i1
LEFT OUTER JOIN item i2
  ON (i1.category_id = i2.category_id AND i1.item_id < i2.item_id)
GROUP BY i1.item_id
HAVING COUNT(*) < 4
ORDER BY category_id, date_listed;

Tôi giả sử là khóa chính của item bảng là item_id và đó là một sự giả tạo đơn điệu ngày càng tăng. Nghĩa là, một giá trị lớn hơn trong item_id tương ứng với một hàng mới hơn trong item .

Đây là cách hoạt động:đối với mỗi mục, có một số mục khác mới hơn. Ví dụ:có ba mục mới hơn mục mới nhất thứ tư. Không có mặt hàng nào mới hơn mặt hàng mới nhất. Vì vậy, chúng tôi muốn so sánh từng mục (i1 ) vào tập hợp các mục (i2 ) mới hơn và có cùng danh mục với i1 . Nếu số lượng các mục mới hơn đó ít hơn bốn, i1 là một trong những chúng tôi bao gồm. Nếu không, đừng bao gồm nó.

Cái hay của giải pháp này là nó hoạt động cho dù bạn có bao nhiêu danh mục và tiếp tục hoạt động nếu bạn thay đổi các danh mục. Nó cũng hoạt động ngay cả khi số lượng mục trong một số danh mục ít hơn bốn.

Một giải pháp khác hoạt động nhưng dựa vào tính năng biến người dùng MySQL:

SELECT *
FROM (
    SELECT i.*, @r := IF(@g = category_id, @r+1, 1) AS rownum, @g := category_id
    FROM (@g:=null, @r:=0) AS _init
    CROSS JOIN item i
    ORDER BY i.category_id, i.date_listed
) AS t
WHERE t.rownum <= 3;

MySQL 8.0.3 đã giới thiệu hỗ trợ cho các chức năng cửa sổ chuẩn SQL. Bây giờ chúng ta có thể giải quyết loại vấn đề này theo cách các RDBMS khác làm:

WITH numbered_item AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY category_id ORDER BY item_id) AS rownum
  FROM item
)
SELECT * FROM numbered_item WHERE rownum <= 4;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cài đặt mysql-python (Windows)

  2. Ràng buộc khóa ngoại MySQL, xóa theo tầng

  3. MySQL tham gia với mệnh đề where

  4. Làm thế nào để đặt lại mật khẩu gốc mysql?

  5. Di chuyển MySQL sang PostgreSQL trên AWS RDS, Phần 1