SQL Server 2008中替代导向/滞后函数的方法

12

我想将当前行与下一行的值进行比较。SQL有LEADLAG函数来获取下一个和前一个值,但由于我正在使用SQL Server 2008,所以无法使用它们。

那么我该怎么办呢?

我有一个包含输出的表。

+----+-------+-----------+-------------------------+
| Id | ActId |  StatusId |       MinStartTime      |
+----+-------+-----------+-------------------------+
| 1  |  42   | 1         | 2014-02-14 11:17:21.203 |
| 2  |  42   | 1         | 2014-02-14 11:50:19.367 |
| 3  |  42   | 1         | 2014-02-14 11:50:19.380 |
| 4  |  42   | 6         | 2014-02-17 05:25:57.280 |
| 5  |  42   | 6         | 2014-02-19 06:09:33.150 |
| 6  |  42   | 1         | 2014-02-19 06:11:24.393 |
| 7  |  42   | 6         | 2014-02-19 06:11:24.410 |
| 8  |  42   | 8         | 2014-02-19 06:44:47.070 |
+----+-------+-----------+-------------------------+

我想要做的是,如果当前行状态为1,并且下一行状态为6,并且两次时间相同(分钟级别),则我想获取状态为1的行。

例如:Id 6行状态为1,Id 7行状态为6,但两个时间相同,即2014-02-19 06:11

所以我想获取状态为1的行或id,即id 6。

3个回答

13
在您的情况下,id 似乎是数字,您可以进行自连接:
select t.*
from table t join
     table tnext
     on t.id = tnext.id - 1 and
        t.StatusId = 1 and
        tnext.StatusId = 6 and
        datediff(second, t.MinStartTime, tnext.MinStartTime) < 60;

这并不是完全相同的一分钟。它在60秒内。你真的需要完全相同的日历时间吗?如果是这样,你可以这样做:

select t.*
from table t join
     table tnext
     on t.id = tnext.id - 1 and
        t.StatusId = 1 and
        tnext.StatusId = 6 and
        datediff(second, t.MinStartTime, tnext.MinStartTime) < 60 and
        datepart(minute, t.MinStartTime) = datepart(minute, tnext.MinStartTime);

也许上述解决方案假设 Id 列中没有空洞。 - Riz
感谢您的时间和完美解决方案...我正在比较时间,使用CONVERT(char(16),t1.MinStartTime,120)。这样可以返回分钟级别的时间...这种方法有问题吗? - Mahajan344
@Spenzo . . . 不,那是一个很好的方法。但是谁能记得住convert()的所有格式,所以我倾向于找到其他解决方案(例如答案中的解决方案)。 - Gordon Linoff
根据Gordon的出色答案,我进行了更复杂的多表连接跟进。 - ScottLenart
谢谢@GordonLinoff。你总是一个超级巨星 :) - ViKiNG

0
我会提供一个非常简单的解决方案,如果你没有顺序行ID而是有不同的步长(比如有些记录已经被删除了..):
declare @t table(id int, obj_name varchar(5))

insert @t select 1,'a'

insert @t select 5,'b'

insert @t select 22,'c'

insert @t select 543,'d'

---------------------------------
select *from @t

示例源表 @t:

---------------------------------
id  obj_name

1   a

5   b

22  c

543 d

---------------------------------

使用自连接进行选择

select obj_name_prev=tt.obj_name, obj_name_next=min(t.obj_name)

from @t t

join @t tt on tt.id < t.id

group by tt.obj_name

结果:

---------------------------------
obj_name_prev   obj_name_next

a   b

b   c

c   d

---------------------------------

0

分享一下使用Gordon的基础框架创建的两个不同表格进行更复杂的连接。请原谅具体的对象名称,但你会明白要点。用于获取样本从一个到另一个的百分比变化。

选择      fm0.SAMPLE curFMSample     ,fm1.SAMPLE nextFMSample     ,fm0.TEMPERATURE curFMTemp     ,fm1.TEMPERATURE nextFMTemp     ,ABS(CAST((fm0.Temperature-fm1.Temperature)AS DECIMAL(4,0))/ CAST(fm0.TEMPERATURE AS DECIMAL(4,0)))AS fmTempChange     ,fm0.GAUGE curFMGauge     ,fm1.GAUGE nextFMGauge     ,ABS(CAST((fm0.GAUGE-fm1.GAUGE)AS DECIMAL(4,4))/ CAST(fm0.GAUGE AS DECIMAL(4,4)))AS fmGaugeChange     ,fm0.WIDTH curFMWidth     ,fm1.WIDTH nextFMWidth     ,ABS(CAST((fm0.Width-fm1.Width)AS DECIMAL(4,2))/ CAST(fm0.Width AS DECIMAL(4,2)))AS fmWidthChange     ,cl0.TEMPERATURE curClrTemp     ,cl1.TEMPERATURE nextClrTemp     ,ABS(CAST((cl0.Temperature-cl1.Temperature)AS DECIMAL(4,0))/ CAST(cl0.TEMPERATURE AS DECIMAL(4,0)))AS clrTempChange 从     dbo.COIL_FINISHING_MILL_EXIT_STR02 fm0     INNER JOIN dbo.COIL_FINISHING_MILL_EXIT_STR02 fm1 ON(fm0.SAMPLE = fm1.SAMPLE - 1 AND fm1.coil = fm0.coil)     INNER JOIN dbo.COIL_COILER_STR02 cl0 ON fm0.coil = cl0.coil AND fm0.SAMPLE = cl0.SAMPLE     INNER JOIN dbo.COIL_COILER_STR02 cl1 ON(cl0.SAMPLE = cl1.SAMPLE - 1 AND cl1.coil = cl0.coil) 哪里     fm0.coil = 2015515872

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接