LoginSignup
0
0

GRPUP BY で集計→ max のレコードを抽出(MySQL/MariaDB)のための備忘録

Last updated at Posted at 2024-03-27

見よう見まねでSQL。

このような「食べ放題」テーブルで、

+----+--------------+------------+--------------+
| ID | 学生番号     | 日付       | おにぎり     |
+----+--------------+------------+--------------+
|  1 | 100          | 2024-03-27 |            5 |
|  2 | 100          | 2024-03-22 |            4 |
|  3 | 101          | 2024-03-10 |            7 |
|  4 | 102          | 2024-03-21 |           10 |
|  5 | 101          | 2024-03-15 |            3 |
+----+--------------+------------+--------------+

最後にチャレンジしたスコアを学生ごとに出したい。



+----+--------------+------------+--------------+
| ID | 学生番号     | 日付       | おにぎり     |
+----+--------------+------------+--------------+
|  1 | 100          | 2024-03-27 |            5 |
|  4 | 102          | 2024-03-21 |           10 |
|  5 | 101          | 2024-03-15 |            3 |
+----+--------------+------------+--------------+

上記のようなものを出すには、

SELECT ID,  学生番号,max(日付),おにぎり  FROM 食べ放題
            GROUP BY 学生番号

でいいかな・・・

+----+--------------+-------------+--------------+
| ID | 学生番号     | max(日付)   | おにぎり     |
+----+--------------+-------------+--------------+
|  1 | 100          | 2024-03-27  |            5 |
|  3 | 101          | 2024-03-15  |            7 |
|  4 | 102          | 2024-03-21  |           10 |
+----+--------------+-------------+--------------+

うーん?

環境

  • mysql Ver 15.1 Distrib 10.6.16-MariaDB, for debian-linux-gnu (x86_64) using EditLine wrapper
  • 母艦 Ubuntu22.04 LTS

解決方法

調べてみたらいろいろ方法があるらしい

INNTER JOIN を使う方法

 SELECT ID,学生番号 ,日付 ,おにぎり
  FROM 食べ放題 AS 食べ放題A
  INNER JOIN 
   (
    SELECT max(日付) AS 日付B ,学生番号 AS 学生番号B FROM 食べ放題
     GROUP BY 学生番号B
   )
   AS 食べ放題B
  ON 食べ放題A.学生番号=食べ放題B.学生番号B
  AND 食べ放題A.日付=食べ放題B.日付B;
+----+--------------+------------+--------------+
| ID | 学生番号     | 日付       | おにぎり     |
+----+--------------+------------+--------------+
|  1 | 100          | 2024-03-27 |            5 |
|  4 | 102          | 2024-03-21 |           10 |
|  5 | 101          | 2024-03-15 |            3 |
+----+--------------+------------+--------------+

PARTITON BY を使う方法

GROUP BY を使わない方法。
Rank フィールドを持ったデータを作って、 PARTITON BY で Rank = 1 を抽出する。
こっちがわかりやすいかな。

SELECT 食べ放題Member.ID,食べ放題Member.おにぎり,食べ放題Member.学生番号,食べ放題Member.日付
FROM 
  ( SELECT ROW_NUMBER() OVER (
    PARTITION BY 学生番号
    ORDER BY 日付 DESC
  ) AS 日付Rank,
   ID,
   おにぎり,
   学生番号,
   日付
   FROM  食べ放題
   ) AS 食べ放題Member
   WHERE 食べ放題Member.日付Rank = 1
+------+--------------+--------------+------------+
| ID   | おにぎり     | 学生番号     | 日付       |
+------+--------------+--------------+------------+
|    1 |            5 | 100          | 2024-03-27 |
|    5 |            3 | 101          | 2024-03-15 |
|    4 |           10 | 102          | 2024-03-21 |
+------+--------------+--------------+------------+

うまくいきました。

抽出元を絞り込む

SELECT 食べ放題Member.ID,食べ放題Member.おにぎり,食べ放題Member.学生番号,食べ放題Member.日付
FROM 
  ( SELECT ROW_NUMBER() OVER (
    PARTITION BY 学生番号
    ORDER BY 日付 DESC
  ) AS 日付Rank,
   ID,
   おにぎり,
   学生番号,
   日付
   FROM  食べ放題 WHERE 日付<'2024/03/25'
   ) AS 食べ放題Member
   WHERE 食べ放題Member.日付Rank = 1
+------+--------------+--------------+------------+
| ID   | おにぎり     | 学生番号     | 日付       |
+------+--------------+--------------+------------+
|    2 |            4 | 100          | 2024-03-22 |
|    5 |            3 | 101          | 2024-03-15 |
|    4 |           10 | 102          | 2024-03-21 |
+------+--------------+--------------+------------+
0
0
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
0
0