web-dev-qa-db-ja.com

各グループの最新の2つのレコードを取得する方法

だから、私は次のようなテーブルを持っています:

sn color value
1  red   4
2  red   8
3  green 5
4  red   2
5  green 4
6  green 3

次に、各色の最新の2行が必要です。例:

2  red   8
4  red   2
5  green 4
6  green 3

色ごとに個別のクエリを使用する以外に、それを行う方法は?

ありがとう

3
lost111in

MySQL 8を使用

SELECT sn, color, value
FROM (
  SELECT
    sn,
    color,
    value,
    DENSE_RANK() OVER (PARTITION BY color ORDER BY sn) AS r
  FROM table
) AS t
WHERE t.r <= 2;

MySQL <8の使用

あなたはそれらの特別な変数を使用する必要があります。 このようなもの

3
Evan Carroll

これは、「greatest-n-per-group」問題のバリエーションです。 MySQLだけが実装している場合は、ウィンドウ関数またはLATERAL結合(_CROSS/OUTER APPLY_とも呼ばれる)で使用できます。*

これが機能する1つの方法です。私はそれを「貧乏人の十字架適用」と呼びます:

_select t.*
from 
    ( select distinct color from tbl ) as td    -- for every colour
  left join                                     -- join to the table
    tbl as t                                    -- and get all rows
  on  t.color = td.color                        -- with that color
  and t.sn >= coalesce(                         -- and sn bigger or equal than
      ( select ti.sn                            -- the 2nd higher sn value
        from tbl as ti
        where ti.color = td.color
        order by ti.sn desc
        limit 1 offset 1                        -- 1 + 1st = 2nd
      ), -9223372036854775808    -- the smallest possible bigint value,
          ) ;                    -- to cover cases of colours 
                                 -- with a single appearance, where
                                 -- the subquery returns NULL
_

dbfiddle.uk でテストされています。 _(color, sn)_または_(color, sn, value)_のインデックスがこのクエリで使用されます。異なるcolor値が少ししかない場合は、非常に効率的です。

*:MySQLのフォークであるMariaDBは実際にウィンドウ関数を実装しているため、ROW_NUMBER()RANK()またはDENSE_RANK()などのランキング関数を使用したソリューションがそこで機能します。

1
ypercubeᵀᴹ