sql如何先排序再去重
場景
有一張得分表(score),記錄了用戶每次的得分,同一個人可能有多個得分。
| 1 | tom | 45 |
| 2 | jack | 78 |
| 3 | tom | 34 |
| . | . | . |
需求:找出分數最高的前5個人。
SQL1
首先我們寫個最簡單的sql:
select id, name, score from score order by score desc limit 5;如果sql這樣寫,結果可能是:
| 2 | jack | 78 |
| 1 | tom | 45 |
| 3 | tom | 34 |
排序了,但是沒有去重
SQL2
那么我們加上去重:
select distinct name from score order by score desc limit 5;首先第一點是這個sql未必能執行。在一些數據庫版本,這個sql可以被執行,在一些版本則會提示你order by的字段必須在distinct中存在(見SQL3)。
但是即使能執行,這個sql也得不到預期結果。原因是distinct優先于order by 被數據庫執行。
在執行distinct name的時候,如上文中的數據。是取id=1的數據,還是id=3的數據呢?其實這是數據庫自行決定的。因此,可能會不正確選擇數據。
比如真的執行這個sql,可能去重的結果是:
| 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 byname order by score desc limit 5;也不行,因為在group by的時候,數據庫還是不知道對兩行name一樣的數據,究竟應該留下哪一行。
SQL5
正確的寫法:
select name from score group byname order by max(score) desc limit 5;這樣寫,在執行group by的時候,數據庫就知道要保留score最大的那一行了。
轉載于:https://www.cnblogs.com/dsj2016/p/10679366.html
總結
以上是生活随笔為你收集整理的sql如何先排序再去重的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你知道自己执行的是哪个jre吗?
- 下一篇: cocos2d-x的Android工程开