6

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

丢弃排名> 2的项目。但是我需要的是这样的结果

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. 中的行
    ...

只要找到相同颜色的对就继续,然后按分数降序排列剩下的。

可以在此处找到测试表的导入语句。谢谢你的帮助。

4

2 回答 2

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是组大小的参数。

于 2013-04-23T14:19:13.583 回答
1

您可以这样做ORDER BY (rank <= 2) DESC以获取 rank<=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

于 2013-04-23T11:05:18.800 回答