MYSQL 8  MySQL DBA 也该学学复杂查询了_SQL

MYSQL 一直被diss的就是数据分析尤其在窗口函数这一块,相对于O , S , P三个数据库,MYSQL在这方面基本上属于空白。MYSQL 8 的到来后,这方面也有了改变。在别的数据库上有的专门的课程 T-SQL, PLPGSQL, PLSQL等等,也是否有可能在MYSQL上,随着MYSQL8的使用,出现 M- SQL。

(这里我们使用了MYSQL 官方的练习库 employees)

1 对查询结果的排序

上面这段语句的作用是查找雇员表中每个人最高的工资中工资大于 91530的那些人的员工号和工资数,以及人名,并根据工资来一个从上到下的排序需要一个序号

MYSQL 8  MySQL DBA 也该学学复杂查询了_数据库_02

MYSQL 8  MySQL DBA 也该学学复杂查询了_数据库_03

这样的操作在MYSQL 5.7中如果要操作的话,这是达到同样结果的写法,在MySQL  5.7

MYSQL 8  MySQL DBA 也该学学复杂查询了_数据库_04

但实际上有些查询在MYSQL5.7是不能进行的。

下面这个语句的意思是,根据员工的工资进行一个排序根据每个员工的工号作为一个排序的partition by ,从这里可以看到每个员工的随着在公司工作的年限,越长,工资的涨幅和总数都是一个向上的过程,这样的复杂操作如果在MYSQL 5.7 我是真想不出在一个SQL 中很顺利的完成它。

MYSQL 8  MySQL DBA 也该学学复杂查询了_窗口函数_05

这里使用了DENSE_RANK() 的窗口函数来完成这样的复杂的统计功能。

另外还有一些常用的统计功能,例如统计员工这些年的薪金总和可以使用sum 求和,通过对员工号进行partition 来对数据进行查询。

MYSQL 8  MySQL DBA 也该学学复杂查询了_窗口函数_06

上面的写法算是比较简单的

下面提出一个新的需求,我们需要根据员工每年的工资基数来计算下一年度与上一年度工资的平均数,也就是  (1年 工资  +  第二年工资) /2 为 第二年度的平均工资, 以此类推。

下面这个SQL 就是相关的完成上面的工作的,如果在MYSQL上完成类似的语句,不使用这样的窗口函数,在

MYSQL 8  MySQL DBA 也该学学复杂查询了_窗口函数_07

 

事实上这些也只是窗口函数的冰山一角,以上也仅仅是抛砖引玉,需要学习的东西还很多。

——————————————————————————————

相关的SQL 语句(部分)

select 
ROW_NUMBER() OVER orderby_info AS 'row_number',
sa.emp_no,
sa.salary,
DENSE_RANK() OVER (PARTITION BY sa.emp_no order by sa.salary) as rank_s,
sa.from_date,
sa.to_date
from salaries as sa
where sa.emp_no >= '10001'  and sa.emp_no <= '10010'
WINDOW orderby_info AS (ORDER BY sa.salary desc);
select distinct(em.emp_no), SUM(sa.salary) OVER (PARTITION BY em.emp_no) AS sum
from employees as em 
inner join salaries as sa on em.emp_no = sa.emp_no;
select de.dept_name,sum_info.*
from departments as de 
inner join 
(
select de.dept_no,sum(sa.salary) OVER(PARTITION BY de.dept_no) as salary_rank
from dept_emp as de
inner join employees as em on de.emp_no = em.emp_no
inner join salaries as sa on em.emp_no = sa.emp_no
group by dept_no) as sum_info on de.dept_no = sum_info.dept_no 
with hr_dept as (
select em.emp_no,sa.salary,sa.from_date,sa.to_date from employees as em 
left join salaries as sa on em.emp_no = sa.emp_no)
SELECT
 emp_no,
 salary,
 from_date,
 to_date,
 AVG(salary) OVER(PARTITION BY emp_no ORDER BY salary ROWS UNBOUNDED PRECEDING) AS cur_avg_salary
FROM hr_dept;