SELECT ... LIMITはサブクエリではサポートされていません。恐れ入りますが、自己結合の魔法を解き明かすときが来ました:
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;
真ん中のビットは、同じテーブルの3つのコピーをIDの昇順で結合しようとすることにより、各カテゴリの3番目に低いIDの記事のIDを計算しています。カテゴリの記事が3つ未満の場合、左結合によって制限がNULLになることが保証されるため、外部のWHEREもそのケースを取得する必要があります。
ある時点で「トップ3」の要件が「トップn」に変わる可能性がある場合、これは扱いにくくなり始めます。その場合、最初に個別のカテゴリのリストをクエリしてから、カテゴリごとのクエリを結合するというアイデアを再検討することをお勧めします。
ETA:2つの列での注文:eek、新しい要件! :-)
それはあなたが何を意味するかによります:あなたが最終結果を注文しようとしているだけなら、あなたはそれを最後に叩くことができます問題ありません。ただし、この順序を使用して、選択する3つの記事を選択する必要がある場合は、非常に困難です。
「<」を使用した自己結合を使用して、「ORDERBYarticle_id」の効果を再現しています。残念ながら、「ORDER BY a、b」は実行できますが、できません 「(a、b)<(c、d)」を実行します...「MIN(a、b)」も実行できません。さらに、実際には、issticky、published 、の3列で注文することになります。 article_id、4つ以上の行が返されるのを避けるために、各順序値が一意であることを確認する必要があるため。
できた 列の粗い整数または文字列の組み合わせによって、独自の順序付け可能な値を作成します。
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)
これは実行不可能なほど醜くなり、計算はクエリを効率的にするためにインデックスを使用する可能性をなくします。その時点で、カテゴリごとに個別のLIMITEDクエリを実行する方がよいでしょう。