选择行的间隔,包括具有where和order子句的行

时间:2017-01-03 12:47:40

标签: sql postgresql h2

我有一个表foos(id,fieldA,fieldB,fieldC ...)。我有一个SQL查询,它返回一些行

SELECT * from foos WHERE whereClauseN ORDER BY orderClauseM

现在,从这个集合中我需要选择5行id为X:

  1. 如果id为X的行位于该组的前5行,则必须返回该组的前5行。
  2. 如果id为X的行位于该组的最后5行,则必须返回该组的最后5行。
  3. 如果id为X的行不在前5行而不是最后5行,那么必须返回行X和行X之前的2行以及行X之后的2行。
  4. 如何进行这样的SQL查询(我需要H2和PostgreSql)?

    例如,如果我在执行上面的sql代码后有以下设置(为简单起见,只显示了fieldA):

    | id | fieldA |
    _______________
    | 5  | aaaaa  |
    | 7  | bbbbb  |
    | 23 | tttttt |
    | 22 | ssssss |
    | 12 | rrrrrr |
    | 96 | eeeeee |
    | 48 | qqqqqq |
    | 3  | wwwwww |
    _______________
    

    对于X = 7的情况1,必须返回以下集合:

    | id | fieldA |
    _______________
    | 5  | aaaaa  |
    | 7  | bbbbb  |
    | 23 | tttttt |
    | 22 | ssssss |
    | 12 | rrrrrr |
    _______________
    

    对于案例2,X = 96,必须返回以下集合:

    | id | fieldA |
    _______________
    | 22 | ssssss |
    | 12 | rrrrrr |
    | 96 | eeeeee |
    | 48 | qqqqqq |
    | 3  | wwwwww |
    _______________  
    

    对于X = 12的案例3,必须返回以下集合:

    | id | fieldA |
    _______________
    | 23 | tttttt |
    | 22 | ssssss |
    | 12 | rrrrrr |
    | 96 | eeeeee |
    | 48 | qqqqqq |
    _______________
    

1 个答案:

答案 0 :(得分:1)

假设一行有id X,那么我倾向于使用窗口函数来枚举行并获取“X”值的行号:

with t as (
      select f.*,
             row_number() over (orderClauseM) as seqnum,
             count(*) over () as numrows
      from foo t
      where . . .
      order by orderClauseM
     )
select . . .
from (select t.*,
             max(case when id = X then seqnum end) over () as seqnum_X
      from t
     ) t
where (seqnum_X <= 5 and seqnum <= 5) or
      (seqnum_X >= cnt - 5 and seqnum >= cnt - 5) or
      seqnum between seqnum_X - 2 and seqnum_X + 2;