Mysql5.7版本實現row_number窗口函數的分組排序功能


我在這篇博客https://www.cnblogs.com/chendongblog/p/11887712.html中說過,

在 sql server中outer apply / cross apply 可以更高效率的實現跟row_number函數同等的功能

但mysql 5.7 不僅outer apply / across apply 沒有, row_number也沒有. 哭 !

聽說mysql 8.0 版本 也可以使用row_number函數了

但我們使用的是5.7版本

網上的資料很多, 但感覺不夠簡潔明了, 所以決定自己寫一下

SELECT * FROM
(
SELECT 
@rn:= CASE WHEN @securityid = securityid THEN @rn + 1 ELSE 1 END AS rn,
@securityid:= securityid as securityid,
volume, date
FROM
(SELECT * from us_historicaldaily WHERE DATE <= '2019-05-16' ORDER BY securityid, date DESC) a
,(SELECT @rn=0, @securityid=0) b
)a WHERE rn <= 5

這里有幾點解釋下:

1. 這里對表分組的依據是securityid, 排序的依據是date

相當於有個指針在從上往下滑動,  需要一個用戶變量@securityid來記錄最近一次securityid的值, 

然后跟當前行的securityid列做對比, 如果相等(@securityid = securityid) 說明當前在同一個分組中, @rn 遞增1 ,

否則說明當前組已經變更了 @rn重新計數, 從1開始

2. a表中order by 是必須的,  因為只有排序的表從上往下遍歷才有意義,

而且order by的字段順序要相當於row_number函數的 partition by securityid order by date desc

由於sql的執行順序, order by 排在select 之后, 所以order by語句必須寫在a表中, 而不是整個sql的末尾(恰好mysql支持order by語句寫在表中)

3. b表也是必須的, b表相當於在a表后面加兩個字段初始化這兩個變量的值, 也可以用set關鍵字初始化, 但我還是喜歡用表.

結果如下

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM