对于每一行,在它的分区中的行集被称为它的窗口帧。
一些窗口函数只作用在窗口帧中的行上,而不是整个分区。
默认情况下,如果使用ORDER BY,则帧包括从分区开始到当前行的所有行,以及后续任何与当前行在ORDER BY子句上相等的行。
如果ORDER BY被忽略,则默认帧包含整个分区中所有的行。
一个窗口函数在一系列与当前行有某种关联的表行上执行一种计算。
行保留它们独立的标识。
在这些现象背后,窗口函数可以访问的不仅仅是查询结果的当前行。
SELECT xxxx,XX,XX,AVG(XX) OVER(PARTITION BY xxxx) FROM x;
一个窗口函数调用总是包含一个直接跟在窗口函数名及其参数之后的OVER子句。
OVER子句决定究竟查询中的哪些行被分离出来由窗口函数处理。
OVER子句中的PARTITION BY子句指定了将具有相同PARTITION BY表达式值的行分到组或者分区。对于每一行,窗口函数都会在当前行同一分区的行上进行计算。
举例:
SELECT depname,empno,salary,avg(salary) OVER(PARTITION BY depname) FROM empsalary;
SELECT xxxx,XX,XX,rank() OVER(PARTITION BY xxxx ORDR BY XXX DESC) FROM x;
如上所示,rank函数在当前行的分区内按照ORDER BY子句的顺序为每一个可区分的ORDER BY值产生了一个数字等级。rank不需要显式的参数,因为它的行为完全决定于OVER子句。
举例:
SELECT depname,empno,salary, rank() OVER (PARTITION BY depname ORDER BY salary DESC) FROM empsalary;
当一个查询涉及到多个窗口函数时,可以将每一个分别写在一个独立的OVER子句中。
但如果多个函数要求同一个窗口行为时,这种做法是冗余的而且容易出错的。
替代方案是,每一个窗口行为可以被放在一个命名的WINDOW子句中,然后在OVER中引用它。
SELECT sum(salary) OVER w, avg(salary) OVER w
FROM empsalary
WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);
窗口函数只允许出现在查询的SELECT列表和ORDER BY子句中。
窗口函数的执行逻辑是在处理完这些子句之后。
可以在窗口函数的参数中包括一个聚集函数,但反过来不行。
如果需要在窗口计算执行后进行过滤或者分组,我们可以使用子查询。例如:
SELECT depname, empno, salary FROM
(SELECT depname, empno, salary,rank() OVER (PARTITION BY depname ORDER BY salary DESC,empno) AS pos
FROM empsalary
) AS ss
WHERE pos < 3;