本题涉及到一个关键function--开窗函数
,SQL的一些只能通过子查询
、存储过程
来实现的复杂步骤都可以通过开窗函数
实现。MSSQLServer
、Oracle、DB2
等主流数据库中都提供了对开窗函数的支持,不过非常遗憾的是 MYSQL
暂时还未对开窗函数给予支持。开窗函数
不像普通聚合函数
那样每组只返回一个值,开窗函数
可以为每组返回多个值,开窗函数
执行聚合计算的行集组
是窗口。
开窗函数--每一行添加“工资小于5000的员工人数”
SELECT fname, fcity, fsalary, count(*) over() FROM t_person WHERE fsalary < 5000
非开窗函数(普通聚合函数)--每一行添加“工资小于5000的员工人数”
SELECT fname, fcity, fsalary, (select count(*) from t_person where fsalary < 5000) FROM t_person WHERE fsalary < 5000
开窗函数
格式:
函数名(column) OVER(选项)
OVER(选项)
这样的一个后缀,表示这是一个开窗函数
而不是聚合函数
。所有的聚合函数
都可以经过OVER修饰变成开窗函数
。
COUNT(*) OVER()
对于查询结果的每一行返回相应的结果。OVER(选项)括号中的相应选项可以对于聚合函数的运算窗口范围进行修改。如果OVER()中为空,则是对所有范围进行聚合运算。
SELECT fname,fcity,fage,fsalary,count(*) over(partition by fcity) FROM t_person
这样的结果能够在每一行返回,各个城市的人数
**开窗函数可以在OVER(选项)中使用ORDER BY
子句来制定排序规则。
本题题解:
SELECT emp_no, salary, SUM(salary) OVER(ORDER BY emp_no ROWS BETWEEN unbounded preceding AND current row) AS running_total FROM salaries WHERE to_date = '9999-01-01'
其中OVER()之中的语句涉及到一个窗口函数运行范围的限定。
方法二 语句逻辑(自循环)
SELECT s1.emp_no, s1.salary, (SELECT SUM(s2.salary) FROM salaries s2 ORDER BY s2.emp_no WHERE s2.emp_no <= s1.emp_no AND s2.to_date = '9999-01-01') AS running_total FROM salaries s1 WHERE s1.to_date = '9999-01-01' ORDER BY s1.emp_no