關注我,獲的更多分享。
背景準備實驗環境準備建表語句初始化數據分組排序分組統計分組求最大值背景
在SQL中我們經常遇到一種需求:分組排序,分組求和等各種需求。像這樣的需求,如果在Oracle、SQLserver、postgresql等資料庫中很容易實現,一個開窗函數row_nubmer() over(partition by xxx,yyy order by zzz)就可以解決。
但是在MySQL8.0版本之前,是沒有這樣的開窗函數的。好在8.0之後的版本已經內置了開窗函數。不必自己寫實現邏輯了。但是我們目前還有很多人在使用5.7版本。那麼在5.7版本中,如何實現開窗函數的功能呢?
準備實驗環境
準備建表語句
CREATETABLE`emp`(`id`int(11)NOTNULL,`emp_name`varchar(255)DEFAULTNULL,`dept_no`varchar(255)DEFAULTNULL,`emp_salary`int(10)DEFAULTNULL,`emp_hire_date`dateDEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;
初始化數據
INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(1,'張三','0001',5000,'2017-01-11');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(2,'李四','0002',1000,'2018-10-10');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(3,'王五','0003',2000,'2018-12-19');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(4,'趙六','0002',4000,'2019-09-11');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(5,'王強強','0001',3000,'2019-03-14');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(6,'劉陽','0002',6000,'2019-08-08');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(7,'周心怡','0003',500,'2015-06-10');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(8,'毛志宇','0004',4500,'2016-09-20');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(9,'劉德仁','0002',3500,'2016-02-25');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(10,'範德武','0001',3000,'2020-02-12');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(11,'梅婷婷','0005',8000,'2013-07-07');INSERTINTO`mysql_db`.`emp`(`id`,`emp_name`,`dept_no`,`emp_salary`,`emp_hire_date`)VALUES(12,'鄭冰','0005',1000,'2014-11-17');
最後的環境如下:
分組排序
需求描述:獲取每一個部門薪水最高的員工的信息。
需求分析:
按照部門分組,每一部門的員工放在一組,然後基於這個組中的數據,按照工資降序排列。然後再根據排序後的結果集,獲取排序為1的數據行即為結果。步驟1的SQL如下:定義兩個變量,row_num_t用於存儲每一個組中的排序結果。dept_no_t用於存儲判斷數據行是否是同一組。同事給他們分別初始化數據。然後再查詢的欄位當中,先判斷一下當前是否和上一行的部門編號是同一個部門編號。如果是同一個部門編號,則將排序結果欄位加1;如果不是同個部門編號,表示要切換為新的組了,這個時候,把排序結果欄位重置為1。selectcasewhen@dept_no_t!= x.dept_no then@row_num_t :=1else@row_num_t :=@row_num_t+1endas sort_result, x.id, x.emp_name,-- x.dept_no,@dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_datefrom emp as x, (select@dept_no_t :='')as t1,(select@row_num_t :=0)as t2orderby dept_no, emp_salary desc;
步驟1的示例結果如下:
步驟2的SQL語句如下:在步驟1的SQL基礎之上,在外出包裹一層查詢,然後時候用where條件獲取上面內層查詢結果中排序為1的數據行。select*from(selectcasewhen@dept_no_t!= x.dept_no then@row_num_t :=1else@row_num_t :=@row_num_t+1endas sort_result, x.id, x.emp_name,-- x.dept_no,@dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_datefrom emp as x, (select@dept_no_t :='')as t1,(select@row_num_t :=0)as t2orderby dept_no, emp_salary desc)as y where y.sort_result =1;
步驟2的示例結果如下:
分組統計
需求描述:累計統計每一個部門下所有員工的工資之和。
分析:按照部門分組,每一部門的員工放在一組,然後基於這個組中的數據,逐行累加該部門下所有員工的工資。
SQL如下:定義一個用於存儲最後每組員工工資之和的變量emp_salary_sum_t,然後再每一行數據是否為同一組數據,如果是同一組數據,則將這行數據的工資,累加到工資之和的變量中;如果不是同一組數據,把當前行的工資賦值給每組工資之和的變量。selectcasewhen@dept_no_t!= x.dept_no then@row_num_t :=1else@row_num_t :=@row_num_t+1endas sort_result,casewhen@dept_no_t!= x.dept_no then@emp_salary_sum_t := x.emp_salary when@dept_no_t= x.dept_no then@emp_salary_sum_t :=@emp_salary_sum_t+ x.emp_salary endas emp_salary_sum, x.id, x.emp_name,-- x.dept_no,@dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_datefrom emp as x,(select@dept_no_t :='')as t1,(select@row_num_t :=0)as t2,(select@emp_salary_sum_t :=0)as t3orderby dept_no, emp_salary desc;
最後示例結果如下:
分組求最大值
需求描述:計算每個員工和部門中工資最高員工的工資差。
需求分析:
根據員工的部門分組,然後判斷得到每組數據中,工資最高的員工的工資。把這個作為一個新列查詢出出來。基於步驟1的結果集中的新列,和員工的工資列做減法得到差值。步驟1SQL語句如下:select case when@dept_no_t!= x.dept_no then @emp_salary_max_t := x.emp_salarywhen@dept_no_t= x.dept_noand x.emp_salary >@emp_salary_max_tthen @emp_salary_max_t := x.emp_salaryelse@emp_salary_max_tendas emp_salary_max, x.id, x.emp_name,@dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_date from emp as x,(select@dept_no_t :='')as t1, (select@emp_salary_max_t :=0)as t4 orderby dept_no, emp_salary desc
步驟1實驗結果如下:
步驟2SQL語句如下:select y.emp_salary_max, y.emp_salary_max - y.emp_salary as cha, y.id, y.emp_name, y.dept_no, y.emp_salary, y.emp_hire_datefrom(selectcasewhen@dept_no_t!= x.dept_no then@emp_salary_max_t := x.emp_salarywhen@dept_no_t= x.dept_no and x.emp_salary >@emp_salary_max_tthen@emp_salary_max_t := x.emp_salary else@emp_salary_max_tendas emp_salary_max, x.id, x.emp_name,@dept_no_t := x.dept_no as dept_no, x.emp_salary, x.emp_hire_date from emp as x,(select@dept_no_t :='')as t1, (select@emp_salary_max_t :=0)as t4 orderby dept_no, emp_salary desc)as y;
步驟2實驗結果如下:
以上就是MySQL5.7版本中,如何使用開窗函數的示例。希望能這篇文章能夠幫到你,也還原你把文章分享給更多的朋友。如果有什麼問題請留言,我看到後會第一時間恢復你。