按固定数量的记录进行分区

时间:2013-11-09 10:37:58

标签: sql postgresql window-functions postgresql-9.0

我想知道如何用固定数量的记录对窗口进行分区。

示例(http://sqlfiddle.com/#!1/7df86)。

CREATE TABLE Games 
(
 id serial primary key, 
 game_no integer not null, 
 points integer,
  constraint game_no unique (game_no)
);

INSERT INTO Games (game_no, points)
VALUES (3123, 5), (3126, 5), (3135, 8), (3128, null), (3130, 1), (3121, 11), 
(3132, 0), (3133, 4), (3110, 7), (3112, null), (3113, 12), (3125, 3),(3134, 8);

我希望三个游戏的积分总和,从最高的游戏数开始,按游戏编号降序排列。像这样。

| GAME_NO | POINTS | SUM_THREE |
|---------|--------|-----------|
|    3135 |      8 |        20 |
|    3134 |      8 |        20 |
|    3133 |      4 |        20 |
|    3132 |      0 |         1 |
|    3130 |      1 |         1 |
|    3128 | (null) |         1 |
|    3126 |      5 |        13 |
|    3125 |      3 |        13 |
|    3123 |      5 |        13 |
|    3121 |     11 |        23 |
|    3113 |     12 |        23 |
|    3112 | (null) |        23 |
|    3110 |      7 |         7 |

如何使用窗口函数完成此操作而不使用子查询?我也不能使用例如with语句。它必须是一个单一的查询,因为将执行它的外部解析器(我无法控制)。这看起来很简单,过去几天我对它不知所措:)

1 个答案:

答案 0 :(得分:1)

您可以使用row_number函数除以3,为每组3个连续行分配唯一编号。然后使用sum作为每个组的分析函数。

SQL Fiddle

with x(game_no, points, grp) as (
  select game_no, points,
         ceil(cast(row_number() over (order by game_no desc) as decimal)/ 3)
  from games
  )
select game_no, points,
       sum(points) over (partition by grp)
from x
order by game_no desc;

您可以使用内联视图而不是构造。

select game_no, points,
       sum(points) over (partition by grp)
from (
      select game_no, points,
             ceil(cast(row_number() over
                   (order by game_no desc) as decimal)/ 3) as grp
      from games
    ) as x
order by game_no desc;

<强> Results

| GAME_NO | POINTS | SUM |
|---------|--------|-----|
|    3135 |      8 |  20 |
|    3134 |      8 |  20 |
|    3133 |      4 |  20 |
|    3132 |      0 |   1 |
|    3130 |      1 |   1 |
|    3128 | (null) |   1 |
|    3126 |      5 |  13 |
|    3125 |      3 |  13 |
|    3123 |      5 |  13 |
|    3121 |     11 |  23 |
|    3113 |     12 |  23 |
|    3112 | (null) |  23 |
|    3110 |      7 |   7 |