【问题标题】:SELECT SQL query helpSELECT SQL 查询帮助
【发布时间】:2009-09-07 05:14:09
【问题描述】:

我正在尝试找出一个有点不寻常的选择查询。

首先,我拥有的是表中单行的 id。我想从表中选择多行(假设是 10),其中单行的 id 我知道在表中位于行集的中间。所以它会选择我知道的 id 之前的 4 行和 id 之后的 5 行(或 5、4)。

如果 id 在表的开头或在表的末尾,它仍然选择 10 行,例如,如果 id 是表中的第二行,它将选择它之前的 1 行和 8 行在它之后。当 id 是最后一行时,它将选择它之前的 9 行(当然,加上带有 id 的行)。

我不确定我是否足够清楚,但我无法以更好的方式解释这一点。

编辑:

这里有更多信息。想象一下这样的表格(简化):

id    title
1     Title 1
2     Title 2
3     Title 3
4     Title 4
5     Title 5
6     Title 6
7     Title 7
8     Title 8
9     Title 9
10    Title 10
11    Title 11
12    Title 12
13    Title 13
14    Title 14
15    Title 15
16    Title 16
17    Title 17
18    Title 18
19    Title 19
20    Title 20
21    Title 21
22    Title 22
23    Title 23
24    Title 24
25    Title 25

现在假设我的 id 是 11,那么查询将选择这些行:

7, 8, 9, 10, **11**, 12, 13, 14, 15, 16

假设 id 为 2,查询将选择:

1, **2**, 3, 4, 5, 6, 7, 8, 9, 10

假设id是25,查询会选择:

16, 17, 18, 19, 20, 21, 22, 23, 24, **25**

等等。我希望现在更清楚了。

【问题讨论】:

  • 您能提供表格列吗?你如何确定是否在行集中?
  • 嗯,它是根据我知道的应该是中间行的 id 来确定的。我在帖子中添加了更多信息。

标签: sql mysql


【解决方案1】:
declare @p_id numeric, @p_range numeric
select @p_id = 4 -- known ID
, @p_range = 10 --range
select * from myTable
where id between (@p_id - (@p_range / 2)) and (@p_id + (@p_range / 2))
order by id

这将选择已知 ID (4) 周围的 10 条记录,5 之前,5 之后。

如果您想要恰好有 10 条记录,则必须进行更多操作,并计算出前后存在多少条记录(在 id = 2 等情况下)

【讨论】:

    【解决方案2】:

    我不是 MySQL 专家,但如果 ID 是连续且完整的,这可能会起作用:

    select ID, your_other_columns from (
      select
        :yourID-ID+0.5 as priority,
        * from T where ID between :yourID-9 and :yourID
        union all
      select
        ID-:yourID as priority,
        * from T where ID between :yourID and :yourID+9
      where ID >= :yourID and :yourID >= ID-9
    ) as T20 order by priority limit 10;
    

    【讨论】:

    • 它们不必是连续的。它们大多是,但有时会出现超过 + 1 的跳跃,因为网站使用交易并且有时会失败。
    • 如果 MySQL 支持 ROW_NUMBER(),ID 中的间隙仍然不会太难。如果没有 ROW_NUMBER,我想不出一个不使用游标或临时行编号表的有效解决方案。
    【解决方案3】:

    单个查询...有点难看;)

    SET @target := 11
    (SELECT *
            FROM (
                    (SELECT * FROM your_table WHERE id <= @target ORDER BY id desc LIMIT 10)
                            UNION
                    (SELECT * FROM your_table WHERE id > @target ORDER BY id asc LIMIT 9)
            ) AS u ORDER BY ABS(CAST(u.id AS signed integer) - @target) ASC LIMIT 10
    ) ORDER BY id;
    

    【讨论】: