質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
GROUP BY

GROUP BYとはSQL文のひとつで、SELECT文において特定の列の値が等しい行ごとに表をグループ化します。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

2108閲覧

[SQL] 特定のカラムごとにまとめて最大値を持つ行を抜き出したい

aruto

総合スコア175

GROUP BY

GROUP BYとはSQL文のひとつで、SELECT文において特定の列の値が等しい行ごとに表をグループ化します。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/05/10 06:10

編集2020/05/10 07:24

前提・実現したいこと

特定のカラムごとにまとめて最大値を持つ行を抜き出したい
こういうときの良いSQLの書き方を教えてほしいです。

該当のソースコード

以下のようなデータで、クラスごとに最大点をとった人の
クラス、点数、名前を抜き出したいです。
同率一位がいた場合は全員抜き出したいです。

対象のデータ
studentテーブル

classpointname
A30佐藤
A60安田
A60鈴木
B60田中
B80高橋
C30山田
C50伊藤

取り出したい形

classpointname
A60安田
A60鈴木
B80高橋
C50伊藤

以下のような副問合せで取り出せそうだと思いましたが、これだとあるクラスの最高点と同じ他の人も抜き出してしまっていました。
(この例だとAの最高点(60)と同じBの田中も抜き出してしまっていました)

SQL

1SELECT 2 s1.class, 3 s1.point, 4 s2.name 5FROM ( 6 SELECT 7 class, 8 MAX(point) AS point 9 FROM 10 student 11 GROUP BY 12 class) s1 13 JOIN student s2 ON s1.point = s2.point

質問したいこと

上記の取り出し方ができるSQLを知りたいです。
また取り出したいデータに対してSQLが複雑な気がするのですが、もっと簡潔な書き方はありますでしょうか。
window関数とかを使えばもっと簡潔にかけそうな気がするのですがよくわかっておりません。
例えば以下のような考え方ではできないのでしょうか。

SQL

1SELECT 2 class, 3 name, 4 MAX(point) OVER (PARTITION BY class) AS max 5FROM 6 student 7WHERE 8 point = max --動かないですが最大値と一致する行を条件にしたいつもり

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/05/10 06:44

同率1位がいた場合はどうするのでしょうか。
aruto

2020/05/10 07:20

そこらへんを全然考慮しておりませんでした。 しかも、上のSQLだと他のクラスの最高点と同じ人も取り出してしまっていました。 同率一位がいた場合は両方とも抜き出したいです。 質問文を編集します。
guest

回答1

0

ベストアンサー

質問の問いの部分に関しては、Maxのpointを条件にするなら、駆動側でMaxを取る必要はありません。
whereの条件とする場合は、__相関副問合せ__の形式になります。

SQL

1SELECT * 2FROM student t1 3WHERE point = ( 4 select max(point) from student where class=t1.class 5 )

ただ、DBMSによっては現状の問い合わせの方式が高速だったりします。

SQL

1SELECT s2.* 2FROM ( 3 SELECT class, MAX(point) AS point 4 FROM student 5 GROUP BY class 6 ) s1 7 inner JOIN student s2 8 ON s1.class=s2.class and s1.point = s2.point

投稿2020/05/10 07:27

編集2020/05/10 07:32
sazi

総合スコア25184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aruto

2020/05/10 08:40

ありがとうございます。 相関副問合せの形式の方はまさにこういう風だったら理解しやすいと思う形です。 まだ副問合せはパット見で理解しづらいので、まずは希望するデータを取り出せるよう練習して慣れてきたら速さにも目を向けるようにしたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問