MYSQL8.0新特性開窗函數體驗報告

對於窗口函數,好比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

 

第二部分:開窗函數和SUM()等聚合函數結合

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)

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

結果:

相關文章
相關標籤/搜索