これはグループあたり最大の問題であり、SQLに関する非常に一般的な質問です。
外部結合を使用して解決する方法は次のとおりです。
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;
item
の主キーを想定しています テーブルはitem_id
です 、そしてそれは単調に増加する疑似キーであること。つまり、item_id
の値が大きくなります item
の新しい行に対応します 。
仕組みは次のとおりです。アイテムごとに、新しいアイテムがいくつかあります。たとえば、4番目に新しいアイテムよりも新しいアイテムが3つあります。非常に新しいアイテムより新しいアイテムはありません。したがって、各アイテムを比較します(i1
)アイテムのセット(i2
)より新しく、i1
と同じカテゴリを持つ 。これらの新しいアイテムの数が4未満の場合、i1
含まれているものの1つです。それ以外の場合は、含めないでください。
このソリューションの優れている点は、カテゴリがいくつあっても機能し、カテゴリを変更しても機能し続けることです。一部のカテゴリのアイテム数が4未満の場合でも機能します。
動作するが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では、SQL標準ウィンドウ関数のサポートが導入されました。これで、他のRDBMSと同じようにこの種の問題を解決できます。
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;