选择行的间隔,包括一些带有 where 和 order 子句的行

Posted

技术标签:

【中文标题】选择行的间隔,包括一些带有 where 和 order 子句的行【英文标题】:Select interval of rows including some row with where and order clauses 【发布时间】:2017-01-03 12:47:39 【问题描述】:

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

SELECT * from foos WHERE whereClauseN ORDER BY orderClauseM

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

    如果id为X的行在集合的前5行,则必须返回集合的前5行。 如果 id X 的行在集合的最后 5 行,则必须返回集合的最后 5 行。 如果 ID 为 X 的行不在前 5 行中,也不在后 5 行中,则必须返回 ID 为 X 的行和 X 行之前的 2 行和 X 行之后的 2 行。

如何进行这样的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 |
_______________

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

| 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 |
_______________

【问题讨论】:

请用您正在使用的数据库标记您的问题。 @Gordon Linoff 我编辑了问题 edit 您的问题并添加一些示例数据和基于该数据的预期输出。 Formatted text 请no screen shots 什么决定了第一个和最后一个? @a_horse_with_no_name 我编辑了 【参考方案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;

【讨论】:

cnt 是什么? 如果对你来说不难的话,请解释一下这行max(case when id = X then seqnum end) over () as seqnum_X @PavelKasotov 。 . . cnt 是表中的总行数(seqnum 的最大值)。 max() 表达式只是将Xseqnum 值“传播”到所有行。

以上是关于选择行的间隔,包括一些带有 where 和 order 子句的行的主要内容,如果未能解决你的问题,请参考以下文章

如何选择行的第一个和最后一个值 之间间隔为5分钟

用于选择行的 Where 语句层次结构

带有 WHERE、AND 和 OR 的 SQL 选择语句

Linq-to-Entities:带有 WHERE 子句和投影的 LEFT OUTER JOIN

Oracle通过带有内部连接和返回n行的子查询的桥表选择查询?

从 Sql 中的表中选择不同的日期间隔