窗口分区
分区 (PARTITION BY
) 子句组可在分析函数的 OVER
子句中进行指定(可选),用来在函数处理行之前输入这些行。窗口分区与聚合函数的 GROUP BY
子句相似,区别在于它仅为每个输入行返回一个结果行。如果您省略窗口分区子句,函数会将所有输入行视为一个分区。
指定窗口分区
您可以在分析函数的 OVER
子句中指定窗口分区,如下所示:
{ PARTITION BY expression[,...] | PARTITION BEST | PARTITION NODES }
有关语法的详细信息,请参阅窗口分区子句。
示例
此主题中的示例使用 调用分析函数 中定义的 allsales
架构:
CREATE TABLE allsales(state VARCHAR(20), name VARCHAR(20), sales INT);
INSERT INTO allsales VALUES('MA', 'A', 60);
INSERT INTO allsales VALUES('NY', 'B', 20);
INSERT INTO allsales VALUES('NY', 'C', 15);
INSERT INTO allsales VALUES('MA', 'D', 20);
INSERT INTO allsales VALUES('MA', 'E', 50);
INSERT INTO allsales VALUES('NY', 'F', 40);
INSERT INTO allsales VALUES('MA', 'G', 10);
COMMIT;
每个州的销售中间值
以下查询使用分析 window-partition-clause 计算每个州的销售中间值。分析函数根据分区进行计算,并在下一个分区开始时重新开始。
=> SELECT state, name, sales, MEDIAN(sales)
OVER (PARTITION BY state) AS median from allsales;
在中间值列中,结果分组到 MA (35) 和 NY (20) 的分区中。
state | name | sales | median
-------+------+-------+--------
NY | C | 15 | 20
NY | B | 20 | 20
NY | F | 40 | 20
-------------------------------
MA | G | 10 | 35
MA | D | 20 | 35
MA | E | 50 | 35
MA | A | 60 | 35
(7 rows)
所有州的销售中间值
以下查询计算了所有州的全部销售的中间值。如果您不结合任何参数使用 OVER()
,则只有一个分区,即整个输入:
=> SELECT state, sum(sales), median(SUM(sales))
OVER () AS median FROM allsales GROUP BY state;
state | sum | median
-------+-----+--------
NY | 75 | 107.5
MA | 140 | 107.5
(2 rows)
大于中间值的销售(评估顺序)
除查询的最后一个 SQL ORDER BY
子句之外,分析函数的评估在所有其他子句之后进行。因此,如果查询检索销售大于中间值的所有行,它会返回错误,因为在分析函数之前应用了 WHERE
子句,这时 m
列尚不存在:
=> SELECT name, sales, MEDIAN(sales) OVER () AS m
FROM allsales WHERE sales > m;
ERROR 2624: Column "m" does not exist
您可以通过在子查询中放入谓词 WHERE sales > m
来解决此问题:
=> SELECT * FROM
(SELECT name, sales, MEDIAN(sales) OVER () AS m FROM allsales) sq
WHERE sales > m;
name | sales | m
------+-------+----
F | 40 | 20
E | 50 | 20
A | 60 | 20
(3 rows)
有关更多示例,请参阅分析查询示例。