對於窗口函數,好比row_number(),rank(),dense_rank(),NTILE(),PERCENT_RANK()等等,如今MySQL8.0+版本已經支持了! sql
這是一個原始數據表,數據用於測試函數
1.使用SQL查看工資排名(注意,這個功能若是沒有開窗函數仍是比較難寫的哦,有興趣能夠試一下, 可是如今卻如此簡單! )測試
SELECT `name`, `dept`, `salary`, row_number () over (PARTITION BY `dept` ORDER BY salary DESC ) AS salary_rank FROM t_user
獲得結果:spa
2.使用開窗函數計算每一個部門工資最高的前3我的 (這個功能若是沒有開窗函數會很複雜)3d
SELECT * FROM ( SELECT `name`, `dept`, `salary`, row_number () over (PARTITION BY `dept` ORDER BY salary DESC) AS salary_rank FROM t_user ) AS tmp WHERE tmp.salary_rank <= 3
獲得結果:code
和上面 row_number()很是相似的一個開窗函數還有 rank() blog
rank函數用於返回結果集的分區內每行的排名,行的排名是相關行以前的排名數加一。簡單來講rank函數就是對查詢出來的記錄進行排名,與row_number函數不一樣的是,rank函數考慮到了over子句中排序字段值相同的狀況,若是使用rank函數來生成序號,over子句中排序字段值相同的序號是同樣的,後面字段值不相同的序號將跳過相同的排名號排下一個,也就是相關行以前的排名數加一,能夠理解爲根據當前的記錄數生成序號,後面的記錄依此類推。排序
dense_rank函數的功能與rank函數相似,dense_rank函數在生成序號時是連續的,而rank函數生成的序號有可能不連續。dense_rank函數出現相同排名時,將不跳過相同排名號,rank值緊接上一次的rank值。在各個分組內,rank()是跳躍排序,有兩個第一名時接下來就是第三名,dense_rank()是連續排序,有兩個第一名時仍然跟着第二名。it
SELECT `name`, `dept`, `salary`, SUM(salary) over (PARTITION BY `dept`) FROM t_user
結果能夠看到,這個語句效果和SUM()配合Group BY 使用效果是同樣的,只是結果集格式不一樣而已:io
可是,在上面的語句中加上ORDER BY以後,結果就徹底不一樣了! 須要特別注意
SELECT `name`, `dept`, `salary`, SUM(salary) over (PARTITION BY `dept` ORDER BY salary ASC) FROM t_user
結果:
總結規律: 有order by;按照排序連續累加;無order by,計算partition by後的和;over()中沒有partition by,計算全部數據總和
同時,order by 的ASC和DESC也會致使結果不一樣!
lag與lead函數是跟偏移量相關的兩個分析函數,經過這兩個函數能夠在一次查詢中取出同一字段的前N行的數據(lag)和後N行的數據(lead)做爲獨立的列,從而更方便地進行進行數據過濾。這種操做能夠代替表的自聯接,而且LAG和LEAD有更高的效率。
lead() over([partition by prov_name [ORDER BY val_cnt]])
lag、lead有三個參數,第一個是表達式或字段,第二個是偏移量,第三個是爲控制默認賦值
例如:lead(field, num, defaultvalue) field須要查找的字段,num日後查找的num行的數據,defaultvalue沒有符合條件的默認值。
SELECT `name`, `dept`, `salary`, lag (salary, 1) over (PARTITION BY `dept` ORDER BY salary DESC) FROM t_user
得出如下結果
分析函數執行後結果,能夠看出來,lag函數就是把同個partition組內的order by排名上一條放到本身後面做爲一個新列,
這個效果在須要錯位相減,作逐差計算增加率之類的時候簡直就是神器!
lead()函數和lag函數左右相反,偏移的方向不一樣而已
SELECT `name`, `dept`, `salary`, lead (salary, 1) over (PARTITION BY `dept` ORDER BY salary DESC) '分析函數結果' FROM t_user
結果: