sql >> Databasteknik >  >> RDS >> Mysql

Hur väljer man de senaste fyra föremålen per kategori?

Detta är det största problemet per grupp, och det är en mycket vanlig SQL-fråga.

Så här löser jag det med ytterskarvar:

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;

Jag antar den primära nyckeln för item tabellen är item_id , och att det är en monotont ökande pseudokey. Det vill säga ett större värde i item_id motsvarar en nyare rad i item .

Så här fungerar det:för varje föremål finns det ett antal andra föremål som är nyare. Till exempel finns det tre objekt nyare än det fjärde senaste objektet. Det finns noll artiklar nyare än det allra senaste objektet. Så vi vill jämföra varje objekt (i1 ) till uppsättningen objekt (i2 ) som är nyare och har samma kategori som i1 . Om antalet av dessa nyare objekt är mindre än fyra, i1 är en av dem vi inkluderar. Annars ska du inte inkludera det.

Det fina med denna lösning är att den fungerar oavsett hur många kategorier du har, och fortsätter att fungera om du ändrar kategorierna. Det fungerar även om antalet artiklar i vissa kategorier är färre än fyra.

En annan lösning som fungerar men förlitar sig på MySQL användarvariabler:

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 introducerade stöd för SQL-standardfönsterfunktioner. Nu kan vi lösa den här typen av problem på det sätt som andra RDBMS gör:

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. SQL Server Azure / 2022 Databas Ledger Tables från Linux.

  2. Välj kolumner från resultatuppsättningen av lagrad procedur

  3. Se om en tabell har en DEFAULT-begränsning i SQL Server med OBJECTPROPERTY()

  4. Dela upp kommaseparerade värden för en kolumn i rad genom Oracle SQL-fråga