前提
➀と➁をSELECTする場合はIDだけにGROUP BYを付ければいいのですが、➂でUNIONする場合はSELECTするカラムすべてにGROUP BYを付けなければエラーになります。
➀:「コメントの本文」をSELECT
➁:「コメントについたタグ」をSELECT
➂: ➀と②をUNIONしてSELECT
知りたいこと
なぜ➂の場合だけ、SELECTするカラムすべてにGROUP BYを付けなければエラーになるのか?理由を知りたいです。
CREATE、INSERT
対象レコードです。
SQL
1-- コメント 2CREATE TABLE my_comments( 3 `ID` int, `lang_id` int, `comment` varchar(10), count_likes int(10), 4 PRIMARY KEY (`ID`), 5 FULLTEXT full_my_comments (`comment`) WITH PARSER ngram ); 6INSERT INTO my_comments 7 (`ID`, `lang_id`, `comment`, `count_likes`) 8 VALUES 9 (1, 1, '眠らないでください', 5), 10 (2, 1, '静かにしてください', 1), 11 (3, 1, '席についてください', 6), 12 (4, 1, 'たまに休んで下さい', 9); 13 14-- タグ 15CREATE TABLE my_tags( 16 `ID` int, `is_official` int, `tag_kind_id` int, `tag_name` varchar(100), `detail` varchar(100), 17 PRIMARY KEY (`ID`), 18 UNIQUE unique_tags (`is_official`, `tag_kind_id`, `tag_name`, `detail`) ); 19INSERT INTO my_tags 20 (`ID`, `is_official`, `tag_kind_id`, `tag_name`, `detail`) 21 VALUES 22 (1, 1, 1, '鈴木', '良い人'), 23 (2, 0, 1, '佐藤', '悪い人'), 24 (3, 1, 2, '指導', '.'); 25 26-- コメントが持っているタグ 27CREATE TABLE my_tag_holders( 28 `comments_ID` int, `tags_ID` int, 29 PRIMARY KEY (`comments_ID`,`tags_ID`) ); 30INSERT INTO my_tag_holders 31 (`comments_ID`, `tags_ID`) 32 VALUES 33 (1, 1),(1, 2),(1, 3), 34 (2, 4), 35 (3, 3);
➀:「コメントの本文」をSELECT
まずこちらは、# ➀-1
から# ➀-2
行目の5つのカラムに対し、# ➀-3
行目で「IDだけでまとめる」よう指定していますが、エラーは起こりません。
SQL
1 -- ➀:「コメントの本文」をSELECT 2 SELECT 3 comments.ID AS comment_id # ➀-1 4 ,comments.lang_id 5 ,comments.comment 6 ,comments.count_likes 7 ,GROUP_CONCAT( 8 tags.ID 9 SEPARATOR '__SEPARATOR__' 10 ) AS tag_ids # ➀-2 11 12 FROM 13 my_comments comments 14 LEFT JOIN my_tag_holders th 15 ON th.comments_ID = comments.ID 16 LEFT JOIN my_tags tags 17 ON tags.ID = th.tags_ID 18 19 -- '指導'を持つコメントを指定 20 WHERE MATCH (comments.comment) AGAINST ('指導' IN BOOLEAN MODE) 21 22 GROUP BY comments.ID # ➀-3 23 ORDER BY comments.count_likes DESC, comments.ID DESC 24 LIMIT 0, 20
②:「コメントについたタグ」をSELECT
またこちらは、# ➁-1
から# ➁-2
行目の5つのカラムに対し、# ➁-3
行目で「IDだけでまとめる」よう指定していますが、エラーは起こりません。
SQL
1 -- ➁:「コメントについたタグ」をSELECT 2 SELECT 3 comments.ID AS comment_id # ➁-1 4 ,comments.lang_id 5 ,comments.comment 6 ,comments.count_likes 7 ,GROUP_CONCAT( 8 tags.ID 9 SEPARATOR '__SEPARATOR__' 10 ) AS tag_ids # ➁-2 11 12 FROM 13 my_comments comments 14 LEFT JOIN my_tag_holders th 15 ON th.comments_ID = comments.ID 16 LEFT JOIN my_tags tags 17 ON tags.ID = th.tags_ID 18 19 -- タグ名を指定するためのJOIN 20 LEFT JOIN my_tag_holders th2 21 ON th2.comments_ID = comments.ID 22 LEFT JOIN my_tags tags2 23 ON tags2.ID = th2.tags_ID 24 25 -- '指導'を持つタグを指定 26 WHERE tags2.tag_name LIKE '%指導%' 27 28 GROUP BY comments.ID # ➁-3 29 ORDER BY comments.count_likes DESC, comments.ID DESC 30 LIMIT 0, 20
➂: ➀と➁をUNIONしてSELECT
疑問なのがこちらで、➀と➁と同じように# ➂-1
から# ➂-2
行目の5つのカラムに対し、同じように# ➂-3
行目で「comment_idだけでまとめる」よう指定しているつもりなのですが、この場合にエラーになります。
SQL
1-- ➂: ➀と➁をUNIONしてSELECT 2SELECT 3 x.comment_id # ➂-1 4 ,x.lang_id 5 ,x.comment 6 ,x.count_likes 7 ,x.tag_ids # ➂-2 8FROM ( 9 ( 10 11 -- ➀:「コメントの本文」をSELECT 12 -- 上と同じなので割愛 13 14 ) UNION ( 15 16 -- ➁:「コメントについたタグ」をSELECT 17 -- 上と同じなので割愛 18 ) 19) AS x 20 21GROUP BY x.comment_id # ➂-3 22ORDER BY x.count_likes DESC, x.comment_id DESC 23LIMIT 0, 20
エラーメッセージ
③の場合のエラーがこちらです。(改行は質問者が追加)
SQL
1#1055 - Expression #2 of SELECT list is not in GROUP BY clause 2and contains nonaggregated column 'x.lang_id' 3which is not functionally dependent on columns in GROUP BY clause; 4this is incompatible with sql_mode=only_full_group_by
試したこと
まず③の場合はGROUP BYを次のようにすればエラー解消できました。
SQL
1# GROUP BY x.comment_id 2 3# ↓SELECTされるカラム名をすべてGROUP BY 4 5GROUP BY x.comment_id, x.lang_id, x.comment, x.count_likes, x.tag_ids
さらに、SELECT @@global.sql_mode;
で確認されるONLY_FULL_GROUP_BY
を解除すると、GROUP BY x.comment_id
のままでもエラー解消できました。
これらのことから、➀➁で平気で、③がエラーになるその違いはGROUP BYに由来するものだと考えられます。
でも私は➀➁③どれもが、『同じカラムに対して同じようにGROUP BYしている認識』なのですが、UNIONした場合は何が異なるのでしょうか?
言い換えるなら、③でSELECTするカラムすべてにGROUP BYを付けなければエラーになるのならば、➀➁だってGROUP BY comments.ID
だけではエラーになるハズではないか?という疑問になります。
環境
サーバー:ConoHa WING
phpMyAdmin:5.1.3-2.el7.remi
MySQL:5.7.27-log

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/04/28 19:23
2022/04/29 03:02 編集
2022/04/29 03:58
2022/04/29 04:14
2022/04/29 07:58 編集
2022/04/29 07:41 編集
2022/04/29 08:20 編集
2022/04/29 08:28 編集
2022/04/29 10:01 編集
2022/04/29 10:08 編集
2022/04/29 10:01
2022/04/29 10:08
2022/04/29 13:23 編集
2022/05/02 08:17 編集