VÄLJ ... LIMIT stöds tyvärr inte i underfrågor, så det är dags att bryta ut magin för självanslutningen:
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;
Biten i mitten räknar ut ID:t för artikeln med tredje lägsta ID för varje kategori genom att försöka slå samman tre kopior av samma tabell i stigande ID-ordning. Om det finns färre än tre artiklar för en kategori kommer den vänstra kopplingen att säkerställa att gränsen är NULL, så den yttre WHERE måste också ta upp det fallet.
Om ditt "topp 3"-krav kan ändras till "topp n" någon gång, börjar detta bli otympligt. I så fall kanske du vill ompröva tanken på att först fråga listan med distinkta kategorier och sedan sammanföra frågorna per kategori.
ETA:Beställning i två kolumner:eek, nya krav! :-)
Det beror på vad du menar:om du bara försöker beställa de slutliga resultaten kan du slå det på slutet utan problem. Men om du behöver använda den här beställningen för att välja vilka tre artiklar som ska väljas är det mycket svårare.
Vi använder en självkoppling med '<' för att återskapa effekten 'ORDER BY article_id' skulle ha. Tyvärr, även om du kan göra "ORDER BY a, b", kan du inte gör '(a, b)<(c, d)'... inte heller kan du göra 'MIN(a, b)'. Dessutom skulle du faktiskt sortera efter tre kolumner, issticky, publicerad och article_id, eftersom du måste se till att varje beställningsvärde är unikt för att undvika att fyra eller fler rader returneras.
Medan du kunde skapa ditt eget beställningsbara värde med något grovt heltal eller strängkombination av kolumner:
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)
det här blir otroligt fult, och beräkningarna kommer att försvaga varje chans att använda indexen för att göra frågan effektiv. Då är det bättre för dig att helt enkelt göra de separata LIMITed-frågorna per kategori.