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

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

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

3回答

5271閲覧

MySQLのSELECTでのGROUP BY句について

papi_tokei

総合スコア106

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

1グッド

1クリップ

投稿2017/08/17 09:06

###前提・実現したいこと
MySQLを勉強しているのですが,少し疑問に思った部分があったので,
疑問を解決したいです.

###使用しているデータ
<都道府県テーブル>
都道府県コード
都道府県名
人口
面積

<市町村テーブル>
都道府県コード
市町村コード
区分
市町村名
人口
面積
世帯数

###該当のソースコード
以下のSQLは市町村数が上位10個の都道府県を表示するためのものです.
適切に動作し,出力結果も正しいです.
ですが,私の認識では,GROUP BYで指定したものか,集約関数しかSELECTのカラムに選択出来ないと思っていました.
しかし,今回はGROUP BYに都道府県コードを設定し,SELECTには都道府県名を指定しています.

sql

1SELECT 都道府県名, COUNT(*) AS 市町村数 FROM 都道府県 JOIN 市町村 USING (都道府県コード) GROUP BY 都道府県コード ORDER BY 市町村数 DESC LIMIT 10;

以下のように,GROUP BYの部分を都道府県名に変更しても.同じ結果が出力されます.
エラーも出ません.

sql

1SELECT 都道府県名, COUNT(*) AS 市町村数 FROM 都道府県 JOIN 市町村 USING (都道府県コード) GROUP BY 都道府県名 ORDER BY 市町村数 DESC LIMIT 10;

###解決したい問題
確かに,都道府県コードと都道府県名は一対一対応なので,取替え可能ですが,
そういう話でもないような気がします.
GROUP BYに指定したもの意外をSELECTに設定できている疑問を解決したいです.

よろしくお願いします.

###補足情報(言語/FW/ツール等のバージョンなど)
DockerでMySQLを実行しています.

x_x👍を押しています

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

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

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

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

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

guest

回答3

0

MySQLの場合、集計しない列を取ってくると、どれか1個を適当に取ってきます(マニュアル)。

ただし、これは標準SQLでは書けないものですので、「値が1つ」とわかっていても、MAX(都道府県名)のような集計関数を挟むのが、より良いやり方です。

投稿2017/08/17 09:18

maisumakun

総合スコア145121

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

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

papi_tokei

2017/08/17 09:37

迅速な回答ありがとうございます. GROUP BYに設定していないものを取ると,値が不定になるのですね. その場合は,MAXなどの集約関数を使えば良いということ,勉強になりました. ベストアンサーは最初に回答いただいた方とさせていただきました.
guest

0

標準SQLであればご認識の通りです。この機能はMySQL拡張です。

12.19.3 MySQL での GROUP BY の処理

MySQL では、選択リストが GROUP BY 句で名前が指定されていない非集約カラムを参照できないように、GROUP BY の使用が拡張されています。つまり、上記のクエリーは MySQL では正当です。この機能を使用すると、不要なカラムのソートおよびグループ化が回避されるため、パフォーマンスを改善できます。

結果の整合性は保証されないようです。

ただし、これは主に、GROUP BY で名前が指定されていない各非集約カラム内のすべての値がグループごとに同じである場合に役立ちます。サーバーは各グループから任意の値を自由に選択できるため、同じ値でなければ、選択した値は不確定です。さらに、ORDER BY 句を追加しても、各グループからの値の選択が影響を受ける可能性はありません。値が選択されたあとに結果セットのソートが発生しますが、ORDER BY によって、サーバーで選択された各グループ内の値は影響を受けません。

無効にすることもできるようです。

MySQL GROUP BY の拡張を無効にするには、ONLY_FULL_GROUP_BY SQL モードを有効にします。これにより、標準 SQL の動作が有効になります。

投稿2017/08/17 09:20

tsuemura

総合スコア663

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

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

papi_tokei

2017/08/17 09:41

非常に詳しく回答いただきありがとうございます. GROUP BYの拡張を無効にも出来るのですね. MySQLも奥が深く難しいですが,地道に勉強していこうと思います.
guest

0

ベストアンサー

GROUP BYで指定したものか,集約関数しかSELECTのカラムに選択出来ない

標準SQLとしてはこの認識で問題ないと思います。

少しリファレンスなどを見た感じでは、MySQLのGROUP BYは標準SQLを拡張した仕様らしく、GROUP BYで指定されていないカラムもSELECTで使用できるようです。
ただし、集約される行にあるどの値が返ってくるかが不確定みたいです。

参照:リファレンス
※日本語版は文がちょっと変ですが、英語版の方も合わせてみてもらえればと思います。

今回のケースでは、「都道府県コードと都道府県名は一対一対応」となっているため確実に想定している値が出ているだけ、という状況なのでしょう。

投稿2017/08/17 09:16

attakei

総合スコア2738

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

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

papi_tokei

2017/08/17 09:35

迅速な回答をありがとうございます. MySQLは標準SQLを拡張したつくりになっているのですね. 別のSQLを試すと,「SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.都道府県.都道府県コード' which is not functionally dependent on columns in GROUP BY clause;」といったエラーが出たので,疑問に思って質問させていただきました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問