MySQL:如何查詢出每一個分組中的 top n 條記錄?

問題描述

需求:mysql

查詢出每個月 order_amount(訂單金額) 排行前3的記錄。算法

例如對於2019-02,查詢結果中就應該是這3條:sql

解決方法

MySQL 5.7 和 MySQL 8.0 有不一樣的處理方法。架構

1. MySQL 5.7

咱們先寫一個查詢語句。併發

根據 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。

最終語句:

執行結果:

2. MySQL 8

MySQL 8 引入了一個 rank() 函數,能夠更簡便的實現排行的功能。

執行結果:

效果和 5.7 中的方法是一致的。

咱們看下語句中的 rank() 方法:

  • PARTITION BY 是指定分區依據,這裏是根據訂單的年、月進行分區。
  • ORDER BY 指定了分區內的排序依據,這裏是根據訂單的 年、月、金額 進行降序排列。

這樣就會自動計算出排行數值。

須要注意的是,這個地方和 5.7 的方法不同:

就是參與排序的幾個值同樣的時候,rank 值是同樣的。

最終的SQL語句:

翻譯整理自:

https://towardsdatascience.co...

若是您有興趣實踐一下,在公衆號「性能與架構」中發送消息:200106,會回覆實踐筆記的下載地址,包含建表語句、測試數據、MySQL5.7和8.0的這2個查詢語句。

推薦閱讀:

相關文章
相關標籤/搜索