2022-07-18 グルーピングした内の最大値を持つレコードを取得
グルーピングした内の最大値を持つレコードを取得
グルーピングした内の最大値を持つレコードを取得しようとして、下記の解説記事が良かった。
not exists
を使うのが最速。row_number()
で順番つけるのが意図がわかりやすい。group by
使うのはいまいち。
【SQL】グループごとに最大の値を持つレコードを取得する方法3選 | Takakisan
方法2: row_number()
select
*
from
(
select
*,
row_number() over (
partition by
user_id
order by
created_at desc
) rownum
from
user_scores
) with_rownum
where
rownum = 1
;
row_number()
に関しては MySQL 8 から使えるみたい。
たとえば、カラムA の値の降順で連番を振りたい時は次のように指定します。
SELECT ROW_NUMBER() OVER (ORDER BY カラムA DESC);
MySQL の ROW_NUMBER() - MySQL の基礎 - MySQL 入門
方法3: not exists
このクエリが読み解くのが難しかった。
select
*
from
user_scores
where
not exists (
select
1
from
user_scores sub
where
user_scores.user_id = sub.user_id
and user_scores.created_at < sub.created_at
) -- user_idが同じで、created_at がより大きいレコード が存在しない
;
1つ目の条件で、大元のfromにしているレコードと、exists内でfromにしているレコードで、同じuser_idのものを探します。 さらに2つ目の条件で、大元のfromにしているレコードより、created_atが大きいレコードを探します。
not existsですので、他にcreated_atが大きいレコードがあったら除外です。 そうすると、created_atの大きさ比べで最後まで勝ち抜いたレコード達だけが選抜される訳です。これでやりたいことが実現できましたね。
パフォーマンス的にはこの方法3のやり方が一番良いみたい。
ただ、最大値が複数あったときに複数取得される点は気をつけたい。