Type something to search...
在 MySQL 5.6 使用 GROUP BY 的筆記

在 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
Tags :
Share :

Related Posts

INSERT…ON DUPLICATE KEY UPDATE ..在 MySQL 5.7.26(Aurora MySQL 2.10.3) 後的行為差異
INSERT…ON DUPLICATE KEY UPDATE ..在 MySQL 5.7.26(Aurora MySQL 2.10.3) 後的行為差異

MySQL 5.7.26 修復了一個 bug #2596684([release note](https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-26.html

read more
[MySQL] 使用 update_all & subquery 可能會鎖住全表
[MySQL] 使用 update_all & subquery 可能會鎖住全表

團隊最近遇到一個 subquery + update_all 會鎖整張表的問題,花了一點時間研究 注意:以下為 MySQL 5.6 的實驗探討,在 MySQL 8.0.21 的這個機制已經被優化了 問題 假設有一份 schema 長這樣,有 users 和 posts 兩張表。 create_table "posts", options: "ENGINE=

read more
[MySQL] 對不存在的 row 加鎖,會造成 Deadlock
[MySQL] 對不存在的 row 加鎖,會造成 Deadlock

[MySQL] 對不存在的 row 加鎖,會造成 Deadlock 一個範例 初始資料設定 CREATE TABLE `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAUL

read more
[MySQL] 跑個 migration 怎麼就倒站了
[MySQL] 跑個 migration 怎麼就倒站了

如果網站正在 migrate 時,剛好遇到一個 transaction 沒有結束,就算只是 SELECT ,也有可能讓網站倒站。 一個血淋淋的例子 某個沒有經驗的工程師 A: 對 users table 做一些簡單的查詢,但是開啟了 transaction 沒有 commit BEGIN; SELECT * FROM users; ...**正在

read more
Postgresql 常用命令
Postgresql 常用命令

$createdb [database_name]$pg_dump [database_name] -f [backup_filename]$psql -f [backup_filename] [database_name]$dropdb [database_name]

read more
MySQL 你到底是在鎖屁喔
MySQL 你到底是在鎖屁喔

剛剛在研究這個簡單的範例: CREATE TABLE `posts` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `content` varchar(255) DEFAULT NULL, `user_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `index_posts_on

read more
[Rails][MySQL] 使用 update_all + JOIN + LIMIT 需注意效能問題
[Rails][MySQL] 使用 update_all + JOIN + LIMIT 需注意效能問題

MySQL 使用 JOIN + update_all 時,若遇到 LIMIT 則會轉為 subquery,需注意效能問題。 Rails 在使用 update_all 時,如果有用到 JOIN,會改用 subquery 的形式改寫,但若 Adapter 為 MySQL 時就會維持,因為 MySQL 語法本身支援 JOIN + UPDATE。但若是包含 LIMIT 時,由於 MySQL 也不支援,所

read more