読んで欲しい人
- 「GROUP BY」クエリを指定した時に、何が起きているのかイマイチイメージが掴めない...
- 「GROUP BY」で取得する時に
ERROR 1055 (42000): Expression xx of SELECT list is not in GROUP BY clause and contains nonaggregated column 'xxx' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
みたいなエラーが出るんですけど。
っていう人はぜひ読んでみてください!
※ この記事では MySQL を使用することを想定しています。
GROUP BY を使用するユースケース
例えば、以下のような DDL で定義されるテーブルがあるとします。
-- 売上テーブル
CREATE TABLE sales (
id INT PRIMARY KEY,
product_name VARCHAR(50),
category VARCHAR(20),
price INT,
quantity INT,
region VARCHAR(10)
);
そして、このテーブルには以下のようなレコードが挿入されているとします。
id | product_name | category | price | quantity | region |
---|---|---|---|---|---|
1 | ノート PC | 電子機器 | 80000 | 2 | 東京 |
2 | マウス | 電子機器 | 3000 | 5 | 大阪 |
3 | 小説 A | 書籍 | 1500 | 3 | 東京 |
4 | キーボード | 電子機器 | 8000 | 1 | 名古屋 |
5 | 参考書 B | 書籍 | 2800 | 2 | 大阪 |
6 | デスク | 家具 | 25000 | 1 | 東京 |
7 | チェア | 家具 | 15000 | 2 | 福岡 |
8 | タブレット | 電子機器 | 45000 | 1 | 大阪 |
9 | 雑誌 C | 書籍 | 800 | 4 | 名古屋 |
10 | ソファ | 家具 | 60000 | 1 | 福岡 |
ここで、あなたは「各カテゴリごとの売上合計を教えて欲しい」と注文を受けました。ここでGROUP BY
クエリの出番です。
GROUP BY
クエリを使用すると、指定した列ごと(今回の場合はcategory
ごと)にレコードのグループを編成し、そのレコードグループに対して集約関数を適用させて値を計算できます。
例えば、
SELECT xxx FROM sales GROUP BY category;
のようにcategory
列でGROUP BY
クエリを実行した結果、以下のようにレコードグループを編成することができます。(あくまでイメージ)
category = "電子機器"
のグループ
id | product_name | category | price | quantity | region |
---|---|---|---|---|---|
1 | ノート PC | 電子機器 | 80000 | 2 | 東京 |
2 | マウス | 電子機器 | 3000 | 5 | 大阪 |
4 | キーボード | 電子機器 | 8000 | 1 | 名古屋 |
8 | タブレット | 電子機器 | 45000 | 1 | 大阪 |
category = "書籍"
のグループ
id | product_name | category | price | quantity | region |
---|---|---|---|---|---|
3 | 小説 A | 書籍 | 1500 | 3 | 東京 |
5 | 参考書 B | 書籍 | 2800 | 2 | 大阪 |
9 | 雑誌 C | 書籍 | 800 | 4 | 名古屋 |
category = "家具"
のグループ
id | product_name | category | price | quantity | region |
---|---|---|---|---|---|
6 | デスク | 家具 | 25000 | 1 | 東京 |
7 | チェア | 家具 | 15000 | 2 | 福岡 |
10 | ソファ | 家具 | 60000 | 1 | 福岡 |
そしてSELECT
句の中で、各レコードグループに対して集約関数を適用させることができます。
例えば、
SELECT category, SUM(price * quantity) as total_sales FROM sales GROUP BY category;
とした場合、各レコードグループごとに以下の値を引っ張ってきてくれます。
- 各レコードグループの
category
- 各レコードグループの中の全レコードの
price * quantitiy
合計値
なので結果は以下のようになります。
category | total_sales |
---|---|
電子機器 | 228000 |
書籍 | 13300 |
家具 | 115000 |
GROUP BY
のだいたいのイメージは掴めましたか?
GROUP BY を使用すると気に注意すべき点
GROUP BY
を使用する時に注意しないといけない点の一つとして、GROUP BY
を使用する場合、SELECT
句で指定できるものは、以下のものに限られます。
-
GROUP BY
で指定される列 - 集約関数の計算結果
これは冒頭のERROR 1055 (42000): Expression xx of SELECT list is not in GROUP BY clause and contains nonaggregated column 'xxx' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
のエラーに関わってきます。
例えば以下のようなsqlを書いた場合、このエラーが返ってきます。
SELECT product_name, category, SUM(price * quantity) as total_sales FROM sales GROUP BY category;
返ってくるエラー
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'sandbox.sales.product_name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
これは一体何が起こっているのでしょうか?
category
でGROUP BY
をした場合に編成されるレコードグループの一つをもう一度みてみましょう。
category = "書籍"
のグループ
id | product_name | category | price | quantity | region |
---|---|---|---|---|---|
3 | 小説 A | 書籍 | 1500 | 3 | 東京 |
5 | 参考書 B | 書籍 | 2800 | 2 | 大阪 |
9 | 雑誌 C | 書籍 | 800 | 4 | 名古屋 |
このグループでは、category
はGROUP BY
で指定された列であり、各レコードグループごとに一意であることが保証されています。
一方で、product_name
に関しては、小説 A
、参考書 B
、雑誌 C
の3つが存在します。
このproduct_name
に対して SELECT
を当てたとしても結局どのレコード(id = 3, 5, 9)のproduct_name
をとってこれば良いかMySQLはわからないため、エラーになってしまいます。
これはid
やregion
についても同様と言えます。また、今回はSUM(price * quantity) as total_sales
という形で集約関数を使用して取得できていますが、price
, quantity
も集約関数を使わずにその列だけで取得しようとする場合、同様のエラー発生がします。
GROUP BY
を使用する際は、この点に注意しましょう!