sql如何先排序再去重

場景

有一張得分表(score),記錄了用戶每次的得分,同一我的可能有多個得分。sql

id name score
1 tom 45
2 jack 78
3 tom 34
. . .

需求:找出分數最高的前5我的。數據庫

SQL1

首先咱們寫個最簡單的sql:code

select 
    id, name, score
from 
    score
order by 
    score desc
limit 5;

若是sql這樣寫,結果多是:排序

id name score
2 jack 78
1 tom 45
3 tom 34

排序了,可是沒有去重it

SQL2

那麼咱們加上去重:table

select 
    distinct name
from 
    score
order by 
    score desc
limit 5;

首先第一點是這個sql未必能執行。在一些數據庫版本,這個sql能夠被執行,在一些版本則會提示你order by的字段必須在distinct中存在(見SQL3)。class

可是即便能執行,這個sql也得不到預期結果。緣由是distinct優先於order by 被數據庫執行。select

在執行distinct name的時候,如上文中的數據。是取id=1的數據,仍是id=3的數據呢?其實這是數據庫自行決定的。所以,可能會不正確選擇數據。im

好比真的執行這個sql,可能去重的結果是:數據

id name score
2 jack 78
3 tom 34

而後再執行一個order by,就會認爲第一名是jack78分,第二名是tom34分。然而其實tom應該是45分,這個45分就在數據庫執行distinct的時候被錯誤的丟棄了,畢竟先執行distinct的時候不知道你到底要哪一個數據。

SQL3

那麼咱們把score加入select中呢?

select 
    distinct name, score
from 
    score
order by 
    score desc
limit 5;

很明顯,這樣寫的執行結果和咱們預期不符。由於若是寫:distinct name,score其實是對name和score一塊兒去重。好比name都是jack,score都是45。那麼這行就會被去掉。

可是問題是正由於把score當作去重的條件了。因此對於同名的人,好比都叫tom,會由於其有兩個分數,致使不能被去重,從而保留兩行記錄。結果就是好像沒有去重。

SQL4

那我不用distinct,用group by進行去重能夠嗎?

select 
    name
from 
    score
group by
    name
order by 
    score desc
limit 5;

也不行,由於在group by的時候,數據庫仍是不知道對兩行name同樣的數據,究竟應該留下哪一行。

SQL5

正確的寫法:

select 
    name
from 
    score
group by
    name
order by 
    max(score) desc
limit 5;

這樣寫,在執行group by的時候,數據庫就知道要保留score最大的那一行了。

相關文章
相關標籤/搜索