關注我「程序猿集錦」,獲取更多分享。
在SQL中我們經常遇到一種需求:分組排序,分組求和等各種需求。像這樣的需求,如果在Oracle、SQLserver、postgresql等數據庫中很容易實現,一個開窗函數row_nubmer() over(partition by xxx,yyy order by zzz)就可以解決。
但是在MySQL8.0版本之前,是沒有這樣的開窗函數的。好在8.0之後的版本已經内置了開窗函數。不必自己寫實現邏輯了。但是我們目前還有很多人在使用5.7版本。那麼在5.7版本中,如何實現開窗函數的功能呢?
準備實驗環境準備建表語句
CREATE TABLE `emp` (
`id` int(11) NOT NULL,
`emp_name` varchar(255) DEFAULT NULL,
`dept_no` varchar(255) DEFAULT NULL,
`emp_salary` int(10) DEFAULT NULL,
`emp_hire_date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (1, '張三', '0001', 5000, '2017-01-11');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (2, '李四', '0002', 1000, '2018-10-10');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (3, '王五', '0003', 2000, '2018-12-19');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (4, '趙六', '0002', 4000, '2019-09-11');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (5, '王強強', '0001', 3000, '2019-03-14');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (6, '劉陽', '0002', 6000, '2019-08-08');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (7, '周心怡', '0003', 500, '2015-06-10');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (8, '毛志宇', '0004', 4500, '2016-09-20');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (9, '劉德仁', '0002', 3500, '2016-02-25');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (10, '範德武', '0001', 3000, '2020-02-12');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (11, '梅婷婷', '0005', 8000, '2013-07-07');
INSERT INTO `mysql_db`.`emp`(`id`, `emp_name`, `dept_no`, `emp_salary`, `emp_hire_date`) VALUES (12, '鄭冰', '0005', 1000, '2014-11-17');
最後的環境如下:
分組排序
需求描述:獲取每一個部門薪水最高的員工的信息。
需求分析:
select
case
when @dept_no_t != x.dept_no then @row_num_t := 1
else @row_num_t := @row_num_t 1
end as 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_date
from
emp as x,
(select @dept_no_t := '') as t1,
(select @row_num_t := 0) as t2
order by
dept_no,
emp_salary desc;
select * from (
select
case
when @dept_no_t != x.dept_no then @row_num_t := 1
else @row_num_t := @row_num_t 1
end as 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_date
from
emp as x,
(select @dept_no_t := '') as t1,
(select @row_num_t := 0) as t2
order by
dept_no,
emp_salary desc
) as y
where y.sort_result = 1;
分組求和
需求描述:累計統計每一個部門下所有員工的工資之和。
分析:按照部門分組,每一部門的員工放在一組,然後基于這個組中的數據,逐行累加該部門下所有員工的工資。
select
case
when @dept_no_t != x.dept_no then @row_num_t := 1
else @row_num_t := @row_num_t 1
end as sort_result,
case
when @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
end as 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_date
from
emp as x,
(select @dept_no_t := '') as t1,
(select @row_num_t := 0) as t2,
(select @emp_salary_sum_t := 0) as t3
order by
dept_no,
emp_salary desc;
分組求最大值
需求描述:計算每個員工和部門中工資最高員工的工資差。
需求分析:
select
case
when @dept_no_t != x.dept_no then @emp_salary_max_t := x.emp_salary
when @dept_no_t = x.dept_no and x.emp_salary > @emp_salary_max_t then @emp_salary_max_t := x.emp_salary
else @emp_salary_max_t
end as 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
order by
dept_no, emp_salary desc
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_date
from (
select
case
when @dept_no_t != x.dept_no then @emp_salary_max_t := x.emp_salary
when @dept_no_t = x.dept_no and x.emp_salary > @emp_salary_max_t then @emp_salary_max_t := x.emp_salary
else @emp_salary_max_t
end as 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
order by
dept_no, emp_salary desc
) as y;
以上就是MySQL5.7版本中,如何使用開窗函數的示例。希望能這篇文章能夠幫到你,也歡迎你把文章分享給更多的朋友。如果有什麼問題請留言,我看到後會第一時間回複你。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!