在 MySQL 5.6 使用 GROUP BY 的筆記
- Database
- 14 Jun, 2020
在 MySQL 5.6,如果使用了 GROUP BY A 欄位,但是 SELECT 的 **B 欄位,沒有加上 aggregate function,且群組裡 row 彼此間 B 欄位 **的值並不相同,則會以 nondeterministic 的方式決定要取出 **B 欄位 **的值。
可參考文件:https://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html
假設有這樣結構的表
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birthday` date DEFAULT NULL,
`gender` tinyint(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
且有這些 row
INSERT INTO `users` (`id`, `name`, `birthday`, `gender`)
VALUES
(1, 'Jack', '1988-01-01', 0),
(2, 'Tim', '1989-01-01', 0),
(3, 'Jane', '1989-02-02', 1),
(4, 'Nico', '1990-03-03', 1);
如果用 SELECT gender, birthday FROM users GROUP BY gender
取出的 birthday 的值,並不保證是什麼值,(實測好像是會拿 id 最小的 row)。
如果想要用 GROUP BY 根據欄位 A 分組,且群組中要留下欄位 B 最小的 row
假設我以性別分組,想要取出男性/女性裡,生日最早的 row。
文件中有提到,ORDER BY 並不會影響 GROUP BY 分組內取出的方式,所以這樣做不會達到預期效果:
SELECT * FROM users GROUP BY gender ORDER BY birthday ASC
查到一個可以用解法是這樣:
SELECT users_a.* FROM users users_a
join (SELECT gender, MIN(birthday) as birthday FROM users GROUP BY gender) users_b
ON users_a.gender = users_b.gender
AND users_a.birthday = users_b.birthday