postgresql 11开始支持sql:2011标准的所有window frame子句

发布时间 2024-01-10 09:34:31作者: zhjh256

PostgreSQL 在2009年发布的8.4版本中开始支持window语法,直到2017-10-5发布了pg 11才完全支持sql:2011中所有的子句(所以具体厂商实现通常要三五年甚至更长才能完成对标准规范的支持)。

窗口函数的语法定义如下:

function_name ([expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ([expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )
window_definition定义如下:
[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]

frame_clause定义如下:

{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]

帧定义里面RANGE ROWS GROUPS的含义:

range, groups的边界都是以peer的最外围作为边界,例如字段值 1,1,1,2,3,3,边界是1或者3时,包含所有的1以及所有的3。

如果order by是一个表达式,那么边界以表达式的值来计算,如果多行表达式的值一致,那么这些行就是一组PEER。

  • groups,相同表达式或列值作为一个peer簇,边界输入为前后N个簇。current_row表示包含当前行所在簇的最大范围。
  • range,当前值的差值作为判断边界的条件。current_row表示包含当前行所在簇的最大范围。

frame_start和frame_end的取值为如下之一:

UNBOUNDED PRECEDING
offset PRECEDING
CURRENT ROW
offset FOLLOWING
UNBOUNDED FOLLOWING

frame_exclusion的取值为如下之一:

EXCLUDE CURRENT ROW
EXCLUDE GROUP
EXCLUDE TIES
EXCLUDE NO OTHERS

window的定义如下:

WINDOW window_name AS ( window_definition ) [, ...]

window_definition 的取值如下:

[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]

window定义在HAVING子句最后,也是就普通SELECT的最后,如下:

[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    [ * | expression [ [ AS ] output_name ] [, ...] ]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
    [ HAVING condition ]
    [ WINDOW window_name AS ( window_definition ) [, ...] ]

示例

lightdb@postgres=# select     
  *,     
  avg(score) over w1,    
  sum(score) over w1,    
  count(score) over w1,    
  first_value(score) over w1,    
  last_value(score) over w1    
from t     
  window w1 as (partition by sub order by score groups between 1 preceding and 6 following)     
order by sub,score desc;  
 sid | sub | des  | score |        avg        |  sum  | count | first_value | last_value 
-----+-----+------+-------+-------------------+-------+-------+-------------+------------
   4 |   1 | 语文 |   100 |              99.5 |   199 |     2 |          99 |        100
   3 |   1 | 语文 |    99 |              96.5 | 289.5 |     3 |        90.5 |        100
   7 |   1 | 语文 |  90.5 |            94.625 | 378.5 |     4 |          89 |        100
   6 |   1 | 语文 |    89 |              91.9 | 459.5 |     5 |          81 |        100
   1 |   1 | 语文 |    81 | 88.41666666666667 | 530.5 |     6 |          71 |        100
   2 |   1 | 语文 |    71 | 80.35714285714286 | 562.5 |     7 |          32 |        100
   5 |   1 | 语文 |    32 | 80.35714285714286 | 562.5 |     7 |          32 |        100
   7 |   2 | 数学 |  99.5 |             98.25 | 196.5 |     2 |          97 |       99.5
   6 |   2 | 数学 |    97 |              97.5 | 292.5 |     3 |          96 |       99.5
   2 |   2 | 数学 |    96 |            95.625 | 382.5 |     4 |          90 |       99.5
   4 |   2 | 数学 |    90 |              92.7 | 463.5 |     5 |          81 |       99.5
   1 |   2 | 数学 |    81 |             90.25 | 541.5 |     6 |          78 |       99.5
   3 |   2 | 数学 |    78 | 79.07142857142857 | 553.5 |     7 |          12 |       99.5
   5 |   2 | 数学 |    12 | 79.07142857142857 | 553.5 |     7 |          12 |       99.5
   1 |   3 | 英语 |   100 |             96.25 |   385 |     4 |          95 |        100
   3 |   3 | 英语 |    95 |              95.6 |   478 |     5 |          93 |        100
   4 |   3 | 英语 |    95 |              95.6 |   478 |     5 |          93 |        100
   2 |   3 | 英语 |    95 |              95.6 |   478 |     5 |          93 |        100
   7 |   3 | 英语 |    93 | 94.16666666666667 |   565 |     6 |          87 |        100
   6 |   3 | 英语 |    87 | 88.71428571428571 |   621 |     7 |          56 |        100
   5 |   3 | 英语 |    56 | 88.71428571428571 |   621 |     7 |          56 |        100
   6 |   4 | 物理 |    71 |              67.4 |   337 |     5 |          65 |         71
   7 |   4 | 物理 |    71 |              67.4 |   337 |     5 |          65 |         71
   5 |   4 | 物理 |    65 | 65.28571428571429 |   457 |     7 |          60 |         71
   4 |   4 | 物理 |    65 | 65.28571428571429 |   457 |     7 |          60 |         71
   3 |   4 | 物理 |    65 | 65.28571428571429 |   457 |     7 |          60 |         71
   1 |   4 | 物理 |    60 | 65.28571428571429 |   457 |     7 |          60 |         71
   2 |   4 | 物理 |    60 | 65.28571428571429 |   457 |     7 |          60 |         71
(28 rows)

lightdb@postgres=# select     
  *,                     
  sum(score) over w1,     
  avg(score) over w1,     
  first_value(score) over w1,     
  last_value(score) over w1     
from t     
  window w1 as (partition by sub order by score::int range between 1 preceding and 6 following)     
order by sub, score;  
 sid | sub | des  | score |  sum  |  avg  | first_value | last_value 
-----+-----+------+-------+-------+-------+-------------+------------
   5 |   1 | 语文 |    32 |    32 |    32 |          32 |         32
   2 |   1 | 语文 |    71 |    71 |    71 |          71 |         71
   1 |   1 | 语文 |    81 |    81 |    81 |          81 |         81
   6 |   1 | 语文 |    89 | 179.5 | 89.75 |          89 |       90.5
   7 |   1 | 语文 |  90.5 | 179.5 | 89.75 |          89 |       90.5
   3 |   1 | 语文 |    99 |   199 |  99.5 |          99 |        100
   4 |   1 | 语文 |   100 |   199 |  99.5 |          99 |        100
   5 |   2 | 数学 |    12 |    12 |    12 |          12 |         12
   3 |   2 | 数学 |    78 |   159 |  79.5 |          78 |         81
   1 |   2 | 数学 |    81 |    81 |    81 |          81 |         81
   4 |   2 | 数学 |    90 |   186 |    93 |          90 |         96
   2 |   2 | 数学 |    96 | 292.5 |  97.5 |          96 |       99.5
   6 |   2 | 数学 |    97 | 292.5 |  97.5 |          96 |       99.5
   7 |   2 | 数学 |  99.5 |  99.5 |  99.5 |        99.5 |       99.5
   5 |   3 | 英语 |    56 |    56 |    56 |          56 |         56
   6 |   3 | 英语 |    87 |   180 |    90 |          87 |         93
   7 |   3 | 英语 |    93 |   378 |  94.5 |          93 |         95
   3 |   3 | 英语 |    95 |   385 | 96.25 |          95 |        100
   4 |   3 | 英语 |    95 |   385 | 96.25 |          95 |        100
   2 |   3 | 英语 |    95 |   385 | 96.25 |          95 |        100
   1 |   3 | 英语 |   100 |   100 |   100 |         100 |        100
   1 |   4 | 物理 |    60 |   315 |    63 |          60 |         65
   2 |   4 | 物理 |    60 |   315 |    63 |          60 |         65
   3 |   4 | 物理 |    65 |   337 |  67.4 |          65 |         71
   4 |   4 | 物理 |    65 |   337 |  67.4 |          65 |         71
   5 |   4 | 物理 |    65 |   337 |  67.4 |          65 |         71
   6 |   4 | 物理 |    71 |   142 |    71 |          71 |         71
   7 |   4 | 物理 |    71 |   142 |    71 |          71 |         71
(28 rows)