LoginSignup
18
14

More than 1 year has passed since last update.

SQLで最新のレコードのみを取り出す方法

Last updated at Posted at 2021-12-24

概要

事例として、購買情報のテーブルを用意しました。
1ユーザは複数の購買IDを持つことが可能です。

🔽入力となるテーブル(テーブル名 : purchases)🔽

purchase_id user_id purchase_date price
1 A 03/01 ¥40,000
2 A 01/01 ¥35,000
3 B 01/01 ¥20,000
4 A 02/01 ¥5,000
5 B 04/01 ¥10,000
6 C 02/01 ¥20,000

今回、各ユーザの最新の購買レコードのみ抽出したテーブルを作成したいとします。
🔽目標となるテーブル🔽

purchase_id user_id purchase_date price
1 A 03/01 ¥40,000
5 B 04/01 ¥10,000
6 C 02/01 ¥20,000

最新レコードのみ抽出するために、「GROUP BYやを使え!」みたいな記事も多いのです。
しかし、GROUP BY対象になるカラム(user_id)や、ORDER BY対象になるカラム(purchace_date)以外のカラム情報も取得したいときに、GROUP BYだとできません。😭

「では、どうやってやるのか?」について、忘備録として残します。

方法

① グループ内で新しい/古いもの順の連番をつける

ROW_NUMBER() OVER(PARTITION BY {グループ化する列} ORDER BY {並びかえる列} ASC/DESC)
とすることで、{並びかえる列}を昇順・降順に並び替え、グループごとに連番(順位)をふることが可能です。

具体例を見てみましょう。

select 
  *
 from (
   select
    *,
    row_number() over (PARTITION BY user_id ORDER BY purchase_date DESC) AS number
    FROM purchases
  )

を用いることによって、以下のテーブルになります。

purchase_id user_id purchase_date price number
1 A 03/01 ¥40,000 1
2 A 01/01 ¥35,000 3
3 B 01/01 ¥20,000 2
4 A 02/01 ¥5,000 2
5 B 04/01 ¥10,000 1
6 C 02/01 ¥20,000 1

② 値が1のものだけ取得する。
次にwhere number = 1のものを取得すれば、最新のレコードのみになります!

結論

以下のコードでOK!


 select 
  *
 from (
   select
    *
    row_number() over (PARTITION BY user_id ORDER BY purchase_date DESC) AS num
    FROM purchases
  )
  where num = 1

もし違ういいやり方知っていれば、是非教えてください!

補足

順位づけの関数はrankrow_numberの2つがあるが、row_numberを推奨。
理由は、作成日が同一のレコードがあった際に、rankだと同じ数字が複数現れるから。

18
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
14