Tôi e rằng SELECT ... LIMIT không được hỗ trợ trong các truy vấn phụ, vì vậy đã đến lúc khám phá phép thuật tự tham gia:
SELECT article.*
FROM article
JOIN (
SELECT a0.category_id AS id, MIN(a2.article_id) AS lim
FROM article AS a0
LEFT JOIN article AS a1 ON a1.category_id=a0.category_id AND a1.article_id>a0.article_id
LEFT JOIN article AS a2 ON a2.category_id=a1.category_id AND a2.article_id>a1.article_id
GROUP BY id
) AS cat ON cat.id=article.category_id
WHERE article.article_id<=cat.lim OR cat.lim IS NULL
ORDER BY article_id;
Bit ở giữa đang tìm ra ID của bài viết có ID thấp thứ ba cho mỗi danh mục bằng cách cố gắng nối ba bản sao của cùng một bảng theo thứ tự ID tăng dần. Nếu có ít hơn ba bài viết cho một danh mục, các phép nối bên trái sẽ đảm bảo giới hạn là NULL, vì vậy WHERE bên ngoài cũng cần chọn trường hợp đó.
Nếu yêu cầu “top 3” của bạn có thể thay đổi thành “top n” tại một thời điểm nào đó, điều này bắt đầu trở nên khó sử dụng. Trong trường hợp đó, bạn có thể muốn xem xét lại ý tưởng truy vấn danh sách các danh mục riêng biệt trước rồi hợp nhất các truy vấn cho mỗi danh mục.
ETA:Đặt hàng trên hai cột:eek, yêu cầu mới! :-)
Nó phụ thuộc vào ý của bạn:nếu bạn chỉ cố gắng sắp xếp các kết quả cuối cùng, bạn có thể đạt được kết quả cuối cùng mà không có vấn đề gì. Nhưng nếu bạn cần sử dụng thứ tự này để chọn ba bài viết sẽ được chọn thì mọi thứ sẽ khó hơn rất nhiều.
Chúng tôi đang sử dụng tự nối với ‘<’ để tạo lại hiệu ứng mà ‘ORDER BY article_id’ sẽ có. Rất tiếc, trong khi bạn có thể thực hiện 'ORDER BY a, b', thì bạn lại không thể làm ‘(a, b) <(c, d)’… bạn cũng không thể làm ‘MIN (a, b)’. Ngoài ra, bạn thực sự đang sắp xếp thứ tự theo ba cột, Issticky, đã xuất bản và article_id, vì bạn cần đảm bảo rằng mỗi giá trị đặt hàng là duy nhất, để tránh trả về bốn hàng trở lên.
Trong khi bạn có thể tạo giá trị có thể đặt hàng của riêng bạn bằng một số nguyên thô hoặc kết hợp chuỗi của các cột:
LEFT JOIN article AS a1
ON a1.category_id=a0.category_id
AND HEX(a1.issticky)+HEX(a1.published_at)+HEX(a1.article_id)>HEX(a0.issticky)+HEX(a0.published_at)+HEX(a0.article_id)
điều này đang trở nên xấu xí một cách khó tin và các phép tính sẽ loại bỏ bất kỳ cơ hội nào sử dụng các chỉ số để làm cho truy vấn hiệu quả. Tại thời điểm đó, tốt hơn hết bạn nên thực hiện các truy vấn LIMITed riêng biệt cho từng danh mục.