窗口分区

分区 (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)

有关更多示例,请参阅分析查询示例