sql >> データベース >  >> RDS >> Mysql

カテゴリごとに最新の4つのアイテムを選択するにはどうすればよいですか?

    これはグループあたり最大の問題であり、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;
    


    1. Oraclenull==nullを決定します

    2. JSON_QUOTE()–MySQLでJSON値として使用される文字列の文字をエスケープする方法

    3. MySQLロールアップの使用方法

    4. トレースフラグ3226を使用してログバックアップログを抑制します