teratailの皆様にはいつもお世話になっております。
MySQLのGROUP BYの挙動についてご教授頂きたい点があるため、今回質問させて頂きました。
###前提・実現したいこと
下記のようなデータが入ったicという名のテーブルがあります。
| id | use_date | in_station | out_station | use | is_request |
|---|---|---|---|---|---|
| 1 | 2017/05/26 | 品川 | 秋葉原 | 130 | 0 |
| 2 | 2017/05/26 | 京急川崎 | 品川 | 300 | 0 |
| 3 | 2017/05/25 | 京成上野 | 日暮里 | 150 | 0 |
| 4 | 2017/05/25 | 秋葉原 | 上野 | 150 | 0 |
| 5 | 2017/05/25 | 品川 | 秋葉原 | 130 | 0 |
| 6 | 2017/05/25 | 京急川崎 | 品川 | 300 | 0 |
| 7 | 2017/05/26 | 品川 | 秋葉原 | 130 | 1 |
| 8 | 2017/05/26 | 京急川崎 | 品川 | 300 | 1 |
| 9 | 2017/05/25 | 京成上野 | 日暮里 | 150 | 0 |
| 10 | 2017/05/25 | 秋葉原 | 上野 | 150 | 0 |
| 11 | 2017/05/25 | 品川 | 秋葉原 | 130 | 1 |
| 12 | 2017/05/25 | 京急川崎 | 品川 | 300 | 1 |
| 13 | 2017/05/26 | 品川 | 秋葉原 | 130 | 0 |
| 14 | 2017/05/26 | 京急川崎 | 品川 | 300 | 0 |
| 15 | 2017/05/25 | 京成上野 | 日暮里 | 150 | 0 |
| 16 | 2017/05/25 | 秋葉原 | 上野 | 150 | 0 |
| 17 | 2017/05/25 | 品川 | 秋葉原 | 130 | 0 |
| 18 | 2017/05/25 | 京急川崎 | 品川 | 300 | 0 |
ここから、SQLで抽出した結果として下記のようになることを想定しています。
use_dateを昇順にした上で、use_date、in_station、out_stationが同一の重複レコードはまとめるuse_date、in_station、out_stationが同一だが、is_request=1とis_request=0が混在している場合は、is_request=1になっているレコードを優先する
| id | use_date | in_station | out_station | use | is_request |
|---|---|---|---|---|---|
| 12 | 2017/05/25 | 京急川崎 | 品川 | 300 | 1 |
| 11 | 2017/05/25 | 品川 | 秋葉原 | 130 | 1 |
| 4 | 2017/05/25 | 秋葉原 | 上野 | 150 | 0 |
| 3 | 2017/05/25 | 京成上野 | 日暮里 | 150 | 0 |
| 8 | 2017/05/26 | 京急川崎 | 品川 | 300 | 1 |
| 7 | 2017/05/26 | 品川 | 秋葉原 | 130 | 1 |
一応下記のようなSQLで、想定通りの結果を取得出来てはいるのですが、いまいち自信が持てないでいます。
SELECT * FROM ( ( SELECT * FROM `ic` WHERE `ic`.`use_date` LIKE "2017-05%" AND `ic`.`is_request` = 1 ) UNION ( SELECT * FROM `ic` WHERE `ic`.`use_date` LIKE "2017-05%" AND `ic`.`is_request` = 0 GROUP BY `ic`.`use_date`, `ic`.`in_station`, `ic`.`out_station` ) ) AS `ic_data` GROUP BY `ic_data`.`use_date`, `ic_data`.`in_station`, `ic_data`.`out_station` ORDER BY `ic_data`.`use_date`, `ic_data`.`id` DESC;
ご教授頂きたい点
今回教えて頂きたい点は以下の通りです。
######1. is_request=1のレコードが優先して表示されるのは、UNIONで先に記述しているから、GROUP BYで優先されたのか
2017/05/26品川->秋葉原となっているレコードはid=1、id=7、id=13の3つが存在します。
UNIONで先にis_request=1を指定したとはいえ、GROUP BYしたら確実にis_request=1であるid=7のレコードになる、という確証は、そういえばどこから得られるのだろうと思いました。
######2. GROUP BYされる際に、代表して表示されるレコードを選ぶ基準
id=4、id=10、id=16はidが違うだけで他が同一ですが、その3つからid=4のレコードが選ばれている理由は何なのでしょうか。
以上2点です。
上記SQLを書いた時には上手くハマったな、と思ったのですが、上記のようなことを考え始めたらだんだん自信無くなってしまいました。
MySQLにご見識お持ちの皆様、ご教授頂けると非常に有り難いです。
何卒、よろしくお願い致します。
###補足
######動作確認環境
MariaDB
######上記テーブル、レコード作成用SQL
CREATE TABLE `ic` ( `id` int(11) NOT NULL AUTO_INCREMENT, `use_date` datetime DEFAULT NULL, `in_station` varchar(32) DEFAULT NULL, `out_station` varchar(32) DEFAULT NULL, `use` int(11) DEFAULT NULL, `is_request` tinyint(1) DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-26T00:00:00','品川','秋葉原',130,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-26T00:00:00','京急川崎','品川',300,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','京成上野','日暮里',150,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','秋葉原','上野',150,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','品川','秋葉原',130,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','京急川崎','品川',300,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-26T00:00:00','品川','秋葉原',130,'1'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-26T00:00:00','京急川崎','品川',300,'1'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','京成上野','日暮里',150,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','秋葉原','上野',150,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','品川','秋葉原',130,'1'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','京急川崎','品川',300,'1'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-26T00:00:00','品川','秋葉原',130,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-26T00:00:00','京急川崎','品川',300,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','京成上野','日暮里',150,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','秋葉原','上野',150,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','品川','秋葉原',130,'0'); INSERT INTO `ic` (`use_date`,`in_station`,`out_station`,`use`,`is_request`) VALUES ('2017-05-25T00:00:00','京急川崎','品川',300,'0');
###お礼
ベストアンサーとても迷ったのですが、疑問点をストレートにご回答頂いた上で具体例まで提示くださったKiyoshiMotoki様をベストアンサーとさせて頂きました。
他の皆様のご回答も、非常に勉強になりました。
訳あって仕事ではほぼ1人でコードを書いているので、経歴長い皆様の具体例など非常に参考になりました。
皆様有難うございました。
回答6件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/05/26 12:13