Postgresql:使用窗口函数对组大小进行分组

时间:2013-04-23 10:49:12

标签: postgresql window-functions

在Postgresql中是否有办法编写一个查询,该查询根据具有限制的列对行进行分组而不丢弃其他行。

假设我有一个包含三列id, color, score的表格,其中包含以下行

1 red 10.0
2 red 7.0
3 red 3.0
4 blue 5.0
5 green 4.0
6 blue 2.0
7 blue 1.0

我可以使用带有以下查询的窗口函数获得基于颜色的分组

SELECT * FROM (
    SELECT id, color, score, rank()
    OVER (PARTITION BY color ORDER BY score DESC)
    FROM grouping_test
) AS foo WHERE rank <= 2;

结果

  id | color | score | rank 
 ----+-------+-------+------
   4 | blue  |   5.0 |    1
   6 | blue  |   2.0 |    2
   5 | green |   4.0 |    1
   1 | red   |  10.0 |    1
   2 | red   |   7.0 |    2

丢弃带有排名&gt;的项目但是,我需要的是像

这样的结果
1 red 10.0
2 red 7.0
4 blue 5.0
6 blue 2.0
5 green 4.0
3 red 3.0
7 blue 1.0

没有丢弃的行。

修改 更准确地说我需要的逻辑:

  1. 获取得分最高的一行
  2. 下一行具有相同颜色和最高分数
  3. 剩余项目得分最高的项目
  4. 与2.相同,但是来自3的行 ......
  5. 只要可以找到具有相同颜色的对,然后按降序分数排序。

    可以找到测试表的import语句here。 谢谢你的帮助。

2 个答案:

答案 0 :(得分:3)

可以使用两个嵌套的窗口函数

来完成
SELECT
  id
FROM (
  SELECT
    id,
    color,
    score,
    ((rank() OVER color_window) - 1) / 2 AS rank_window_id
  FROM grouping_test
  WINDOW color_window AS (PARTITION BY color ORDER BY score DESC)
) as foo
WINDOW rank_window AS (PARTITION BY (color, rank_window_id))
ORDER BY
  (max(score) OVER rank_window) DESC,
  color;

2是组大小的参数。

答案 1 :(得分:1)

您可以ORDER BY (rank <= 2) DESC获取排名&lt; = 2的行高于其他所有行:

SELECT id,color,score FROM (
SELECT id, color, score, rank()
OVER (PARTITION BY color ORDER BY score DESC),
max(score) OVER (PARTITION BY color) mx
FROM grouping_test
) AS foo 
ORDER BY 
  (rank <= 2) DESC, 
  CASE WHEN rank<=2 THEN mx ELSE NULL END DESC,
  id;

http://sqlfiddle.com/#!12/bbcfc/109