我有一个项目表,每个项目都有一个与之相关的日期.如果我将日期与一个项目关联,如何使用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字段.
从元素<8的数据中选择最大值(元素)
联盟
从数据元素> 8中选择min(元素)
但通常认为sql用于面向集合的操作而不是迭代操作更有用.
自连接.
对于表格:
/* 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.这使得代码看起来更线性,更少嵌套,并且如果存在大量嵌套则更容易遵循(同样,在某些重新连接时需要更少的重复).