Window function of Mysql5.7

Use background:

In SQL, we often encounter a requirement: various requirements such as group sorting, group summation, etc. If such a requirement is easy to implement in databases such as Oracle, SQLserver, and postgresql, a window function row_nubmer() over(partition by xxx,yyy order by zzz)can solve it.

But before MySQL8.0, there is no such window function. Fortunately, the version after 8.0 has a built-in window function. You don't have to write the implementation logic yourself. But we still have a lot of people using version 5.7. So in version 5.7, how to realize the function of window opening function?

Prepare the experimental environment

Prepare table statement

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;

Initialization data

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');

The final environment is as follows:

group sort

Requirement description: Obtain the information of the highest paid employee in each department.

demand analysis:

  1. Grouped by department, the employees of each department are placed in one group, and then based on the data in this group, they are sorted in descending order of salary.

  2. Then, according to the sorted result set, obtain the data row sorted as 1 as the result.

  • The SQL for step 1 is as follows:

    Define two variables row_num_tto store the sorted results in each group. dept_no_tIt is used to store and judge whether the data rows belong to the same group. Colleagues initialize data for them separately. Then in the query field, first judge whether the current department number is the same as the department number in the previous row. If it is the same department number, add 1 to the sorting result field; if it is not the same department number, it means switching to a new group, at this time, reset the sorting result field to 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,
    	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;
    
  • An example result of step 1 is as follows:

  • The SQL statement of step 2 is as follows:

  • On the basis of the SQL in step 1, wrap a layer of query outside, and then use the where condition to obtain the data rows sorted as 1 in the above inner layer query results.

  • 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;
    
  • An example result of step 2 is as follows

  •  

    group sum

    Requirement description: Accumulate the sum of the salaries of all employees in each department.

    Analysis: Group by department, put employees in each department in one group, and then add up the salaries of all employees in the department row by row based on the data in this group.

  • The SQL is as follows:

    Define a variable for storing the sum of the salary of each group of employees at the end emp_salary_sum_t, and then check whether each row of data is the same group of data, if it is the same group of data, add the salary of this row of data to the variable of the sum of salary; if Not the same set of data, assign the salary of the current row to the variable of the sum of the salary of each group.

  • 
    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;
    
  • The final example result is as follows:

  •  

    Find the maximum value in groups

    Requirement description: Calculate the salary difference of the highest paid employee in each employee and department.

    demand analysis:

  • Group the employees according to their departments, and then judge to get the salary of the employee with the highest salary in each group of data. Query this out as a new column.
  • Based on the new column in the result set of step 1, subtract the employee's salary column to get the difference.
  • Step 1 SQL statement is as follows:

    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
    
  • The experimental results of step 1 are as follows:

  • Step 2 SQL statement is as follows:

    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;
    
  • The experimental results of step 2 are as follows:

  •  The above is an example of how to use the window function in MySQL 5.7. I hope this article can help you.

Guess you like

Origin blog.csdn.net/qq_45967480/article/details/130124651