当前位置:  开发笔记 > 数据库 > 正文

表中"下一个"和"上一个"的SQL是什么?

如何解决《表中"下一个"和"上一个"的SQL是什么?》经验,为你挑选了2个好方法。

我有一个项目表,每个项目都有一个与之相关的日期.如果我将日期与一个项目关联,如何使用SQL查询数据库以获取表格中的"上一个"和"后续"项目?

不可能简单地添加(或减去)一个值,因为日期之间没有规则的间隙.

一个可能的应用是相册或博客Web应用程序中的"上一个/下一个"链接,其中底层数据位于SQL表中.

我认为有两种可能的情况:

首先,每个日期都是唯一的:

样本数据:

1,3,8,19,67,45

当提供8作为参数时,哪些查询(或查询)将给出3和19?(或第3,8,19行).请注意,并不总是要返回三行 - 在序列的末尾会丢失一行.

其次,如果有一个单独的唯一键来对元素进行排序,那么返回集合"周围"日期的查询是什么?预期的订单是按日期然后是关键.

样本数据:

(key:date) 1:1,2:3,3:8,4:8,5:19,10:19,11:67,15:45,16:8

对'8'的查询返回集合:

2:3,3:8,4:8,16:8,5:19

或者什么查询生成表:

key date prev-key next-key
1   1    null     2
2   3    1        3
3   8    2        4
4   8    3        16
5   19   16       10
10  19   5        11
11  67   10       15
15  45   11       null
16  8    4        5

表顺序并不重要 - 只是next-key和prev-key字段.


TheSoftwareJedi和Cade Roux都有适用于我昨晚发布的数据集的解决方案.对于第二个问题,这两个数据集似乎都失败了:

(key:date) 1:1,2:3,3:8,4:8,5:19,10:19,11:67,15:45,16:8

预期的顺序是按日期然后键,所以一个预期的结果可能是:

2:3,3:8,4:8,16:8,5:19

另一个:

key date prev-key next-key
1   1    null     2
2   3    1        3
3   8    2        4
4   8    3        16
5   19   16       10
10  19   5        11
11  67   10       15
15  45   11       null
16  8    4        5

表顺序并不重要 - 只是next-key和prev-key字段.



1> fatbuddha..:

从元素<8的数据中选择最大值(元素)

联盟

从数据元素> 8中选择min(元素)

但通常认为sql用于面向集合的操作而不是迭代操作更有用.



2> Cade Roux..:

自连接.

对于表格:

/*
CREATE TABLE [dbo].[stackoverflow_203302](
    [val] [int] NOT NULL
) ON [PRIMARY]
*/

带参数 @val

SELECT cur.val, MAX(prv.val) AS prv_val, MIN(nxt.val) AS nxt_val
FROM stackoverflow_203302 AS cur
LEFT JOIN stackoverflow_203302 AS prv
    ON cur.val > prv.val
LEFT JOIN stackoverflow_203302 AS nxt
    ON cur.val < nxt.val
WHERE cur.val = @val
GROUP BY cur.val

您可以使用输出参数将其作为存储过程,或者将其作为相关子查询加入到您正在提取的数据中.

如果没有参数,对于您的数据,结果将是:

val         prv_val     nxt_val
----------- ----------- -----------
1           NULL        3
3           1           8
8           3           19
19          8           45
45          19          67
67          45          NULL

对于修改后的示例,您将其用作相关子查询:

/*
CREATE TABLE [dbo].[stackoverflow_203302](
    [ky] [int] NOT NULL,
    [val] [int] NOT NULL,
    CONSTRAINT [PK_stackoverflow_203302] PRIMARY KEY CLUSTERED (
        [ky] ASC
    )
)
*/

SELECT cur.ky AS cur_ky
        ,cur.val AS cur_val
        ,prv.ky AS prv_ky
        ,prv.val AS prv_val
        ,nxt.ky AS nxt_ky
        ,nxt.val as nxt_val
FROM (
    SELECT cur.ky, MAX(prv.ky) AS prv_ky, MIN(nxt.ky) AS nxt_ky
    FROM stackoverflow_203302 AS cur
    LEFT JOIN stackoverflow_203302 AS prv
        ON cur.ky > prv.ky
    LEFT JOIN stackoverflow_203302 AS nxt
        ON cur.ky < nxt.ky
    GROUP BY cur.ky
) AS ordering
INNER JOIN stackoverflow_203302 as cur
    ON cur.ky = ordering.ky
LEFT JOIN stackoverflow_203302 as prv
    ON prv.ky = ordering.prv_ky
LEFT JOIN stackoverflow_203302 as nxt
    ON nxt.ky = ordering.nxt_ky

输出符合预期:

cur_ky      cur_val     prv_ky      prv_val     nxt_ky      nxt_val
----------- ----------- ----------- ----------- ----------- -----------
1           1           NULL        NULL        2           3
2           3           1           1           3           8
3           8           2           3           4           19
4           19          3           8           5           67
5           67          4           19          6           45
6           45          5           67          NULL        NULL

在SQL Server中,我更喜欢将子查询设为Common表Expression.这使得代码看起来更线性,更少嵌套,并且如果存在大量嵌套则更容易遵循(同样,在某些重新连接时需要更少的重复).

推荐阅读
大大炮
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有