为每个不同的列值返回2个记录的限制

时间:2016-11-30 19:29:12

标签: sql postgresql

假设我有一个如下所示的表:

| Col A | Col B | Col C |
|-------|-------|-------|
|   1   |   A   |  54   |
|   1   |   A   |  56   |
|   1   |   B   |  55   |
|   1   |   B   |  51   |
|   1   |   C   |  36   |
|   1   |   C   |  23   |
|   1   |   D   |  62   |
|   1   |   D   |  11   |
|   2   |   B   |  88   |
|   2   |   B   |  17   |
|   2   |   C   |  56   |
|   2   |   C   |  86   |
|   2   |   D   |  47   |
|   2   |   D   |  29   |

我想要做的就是抓住桌子看起来像这样:

| Col A | Col B | Col C |
|-------|-------|-------|
|   1   |   A   |  54   |
|   1   |   A   |  56   |
|   2   |   B   |  88   |
|   2   |   B   |  17   |

我很确定有办法做到这一点,我只是不知道怎么做。首先,我认为DISTINCT ON选择器可以工作,但只返回每个值的一条记录。在这种情况下,我需要为每个值创建两条记录。

2 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是使用窗口函数将行号添加到您想要的每个数据分区,然后选择行号小于2的任何内容。

With CTE AS (
SELECT colA, ColB, ColC, Row_Number() over (Partition by ColA ORDER By  ColB , ColC) RN
FROM Table)
Select * from cte where RN <=2

由于我不知道你想要的c值是多少,我选择按照colC(升序)排序,因此对于给定的A + B组合,将返回C的最低值。

答案 1 :(得分:0)

with
  grp as (select col_a from table group by col_a) -- It should be only index scan, not scanning the whole table
select * from grp join lateral (
  select * from table 
  where grp.col_a = table.col_a 
  order by <desired order here>
  limit 2) on true -- It also avoiding the full scan if properly indexes provided