我在這篇博客https://www.cnblogs.com/chendongblog/p/11887712.html中說過,html
在 sql server中outer apply / cross apply 能夠更高效率的實現跟row_number函數同等的功能mysql
但mysql 5.7 不只outer apply / across apply 沒有, row_number也沒有. 哭 !sql
據說mysql 8.0 版本 也可使用row_number函數了app
但咱們使用的是5.7版本函數
網上的資料不少, 但感受不夠簡潔明瞭, 我就本身寫一下好了url
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
這裏有幾點解釋下:spa
1. 這裏對錶分組的依據是securityid, 排序的依據是date.net
至關於有個指針在從上往下滑動, 須要一個用戶變量@securityid來記錄最近一次securityid的值, 指針
而後跟當前行的securityid列作對比, 若是相等(@securityid = securityid) 說明當前在同一個分組中, @rn 遞增1 ,code
不然說明當前組已經變動了 @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關鍵字初始化, 但我仍是喜歡用表.
結果以下