[MySQL/PostgreSQL] 如何利用DISTINCT/GROUP BY 解決重複資料,並傳回所有欄位


在資料庫篩選資料時候,常常會遇到重複資料的問題,因此,我們會使用「DISTINCT」及「GROUP BY」這二個SQL語法來過濾重複資料,但若只針對某一個欄位來篩選,那比較簡單一點,若是要符合不重複資料,而且又要回傳所有的欄位時,對於初學者來說就有一點難度,而且這二個語法的操作並不是所有的資料庫都是一樣的,例如在MySQL和PostgreSQL中這些指令的用法就會有一點不同,怎麼說呢?讓我們用實例來做說明吧。

示範表格:表格名稱為「DemoTable

範例說明

目的:在資料庫中,篩選出「Level」的資料,但只需要傳回任何一筆,避免傳回多筆的重複資料,例如我想要找出Leve=A、B、C、D各一筆資料出來,並且要傳回所有的資料庫欄位

我們先逐一來看一下範例,這樣比較了解差別所在:

● 範例一:select distinct(level) from DemoTable

這樣的篩選方式,在MySQL、PostgreSQL都適合,且的確可以把Level篩選出來,但卻只會回傳Level這個欄位,不符合我們要回傳所有欄位的需求

● 範例二:select * from DemoTable group by level (適合MySQL)

要篩選出所有欄位,最直覺的想法就是用「*」,此時只要配合GROUP BY就可以達成我們要的結果了

以上的語法在MySQL上是可以正常執行的,但同樣的語法在PostgreSQL中就會出現錯誤了,這會讓新手混亂呀,像我就覺得很奇怪,為什麼會錯呢?原來同樣的指令,在不同資料庫中用法有時候是會不同的

● 範例三:select distinct on (level) * from DemoTable (適合PostgreSQL)

既然範例二的語法無法在PostgreSQL中使用,那麼PostgreSQL要怎麼來篩選呢?我自己用的方式是回到「distinct」這個指令中,只是後面要加「on (欄位)」,再配合「*」就可以篩選出來囉,當然這樣的用法在MySQL中也會失敗

小結:經過幾次的經驗以後,才了解到並非所有SQL的語法效果在每個資料庫上都是一樣的,所以當你覺得語法明明沒錯,但結果卻不是預期的資料時,那麼可以檢查一下你用的資料庫,是否適合該語法的操作。

延伸閱讀:
SQL Fiddle § 線上練習SQL語法的測試網站,支援MySQL、PostgreSQL、SQLite
[筆記] MYSQL/PostgreSQL語法中的LIMIT、OFFSET用法範例說明