需求:mysql
查詢出每個月 order_amount(訂單金額)
排行前3的記錄。算法
例如對於2019-02
,查詢結果中就應該是這3條:sql
MySQL 5.7 和 MySQL 8.0 有不一樣的處理方法。架構
咱們先寫一個查詢語句。併發
根據 order_date
中的年、月
,和order_amount
進行降序排列。函數
而後,添加一個新列:order_amount
(本條記錄在本月中的名次)。高併發
執行結果:性能
能夠看到,根據年、月、訂單金額
排序了,還多了一列order_rank
,顯示出了本條記錄在本月的訂單金額排名狀況。測試
上面SQL中比較個性的是這部分:spa
@current_month
和@order_rank
是咱們自定義的變量。
使用 :=
能夠動態建立一個變量,而不須要使用 set
命令。
這句的含義:
取得order_date
中的月份值,賦值給current_month
,這樣就能夠跟蹤每一個月份。
這句的含義:
比較 current_month
和本條記錄中的月份,若是同樣,order_rank
自增1,不然,置爲1。
注意,@current_month
是在 @order_rank
的後面,例如執行到這條記錄時:
if
判斷中,MONTH(order_date)
值爲 2,而 current_month
值爲 1,仍是上條記錄設置的。
接下來,把上面的SQL語句做爲一個子查詢,而後使用一個 where
條件就能夠輕鬆拿到每組的 top 3。
最終語句:
執行結果:
MySQL 8 引入了一個 rank()
函數,能夠更簡便的實現排行的功能。
執行結果:
效果和 5.7 中的方法是一致的。
咱們看下語句中的 rank()
方法:
PARTITION BY
是指定分區依據,這裏是根據訂單的年、月
進行分區。ORDER BY
指定了分區內的排序依據,這裏是根據訂單的 年、月、金額
進行降序排列。這樣就會自動計算出排行數值。
須要注意的是,這個地方和 5.7 的方法不同:
就是參與排序的幾個值同樣的時候,rank
值是同樣的。
最終的SQL語句:
翻譯整理自:
https://towardsdatascience.co...
若是您有興趣實踐一下,在公衆號「性能與架構」中發送消息:200106,會回覆實踐筆記的下載地址,包含建表語句、測試數據、MySQL5.7和8.0的這2個查詢語句。
推薦閱讀: