有一張得分表(score),記錄了用戶每次的得分,同一我的可能有多個得分。sql
id | name | score |
---|---|---|
1 | tom | 45 |
2 | jack | 78 |
3 | tom | 34 |
. | . | . |
需求:找出分數最高的前5我的。數據庫
首先咱們寫個最簡單的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
那麼咱們加上去重: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的時候不知道你到底要哪一個數據。
那麼咱們把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,會由於其有兩個分數,致使不能被去重,從而保留兩行記錄。結果就是好像沒有去重。
那我不用distinct,用group by進行去重能夠嗎?
select name from score group by name order by score desc limit 5;
也不行,由於在group by的時候,數據庫仍是不知道對兩行name同樣的數據,究竟應該留下哪一行。
正確的寫法:
select name from score group by name order by max(score) desc limit 5;
這樣寫,在執行group by的時候,數據庫就知道要保留score最大的那一行了。