在T-SQL查询中,基于datetime列来替换列值

问题描述

|| 不好意思的标题表示歉意,如果没有样本,就不确定如何解释: 我正在尝试在查询中返回一列,当结果集上的datetime列的小时发生变化时,该列在0和1之间交替。有人建议这样做的好方法吗?或如何通过CTE完成 我开始研究使用CTE,但距离还很远,希望有一种更简单的方法。有关电流输出和所需输出的最基本示例,请参见下文。请注意,我创建了一个[band]列,只要时间在同一天,它就会执行我想要的操作。当然,当日期超过一天时,它就会中断。
declare @test as table(id int,dt datetime,comment varchar(50))

insert into @test values(1,\'2011-01-01 07:00\',\'one\')
insert into @test values(2,\'2011-01-01 07:30\',\'two\')
insert into @test values(3,\'2011-01-02 07:50\',\'three\')
insert into @test values(4,\'2011-01-03 08:00\',\'four\')
insert into @test values(5,\'2011-01-03 08:50\',\'five\')
insert into @test values(6,\'2011-01-03 09:00\',\'six\')
insert into @test values(7,\'2011-01-03 10:00\',\'seven\');

select *,DATEPART(HOUR,dt) % 2 as [band]
from @test
当前输出
1   2011-01-01 07:00:00.000 one     1
2   2011-01-01 07:30:00.000 two     1
3   2011-01-02 07:50:00.000 three   1
4   2011-01-03 08:00:00.000 four    0
5   2011-01-03 08:50:00.000 five    0
6   2011-01-03 09:00:00.000 six     1
7   2011-01-03 10:00:00.000 seven   0
所需的输出
1   2011-01-01 07:00:00.000 one     1
2   2011-01-01 07:30:00.000 two     1
3   2011-01-02 07:50:00.000 three   0
4   2011-01-03 08:00:00.000 four    1
5   2011-01-03 08:50:00.000 five    1
6   2011-01-03 09:00:00.000 six     0
7   2011-01-03 10:00:00.000 seven   1
请注意,我希望[band]列交替显示,因为行中的日期时间更改为新小时。无论是当天的下一个小时还是第二天的另一个小时。     

解决方法

        怎么样?
SELECT *,(dense_rank() over (order by Dateadd(hh,Datediff(hh,dt),0))) % 2 as [band]
FROM @test
我现在手头没有sql。但 dateadd / datediff清除小时数 然后density_rank像rownumber一样对它们进行排序,但不对重复项进行编号 那么%2会执行您在原始查询中的操作。     ,        据我了解的问题: 您想将每个记录的datetime值与先前的记录进行比较,如果小时或高于一个小时的任何值已更改,则返回1,否则返回0。 没有很好的方法可以执行此操作-您必须进行迭代。在SQL中,迭代意味着游标:
DECLARE timeLoop CURSOR FOR
SELECT ID,DT 
FROM @test
ORDER BY ID

DECLARE @Id Int
DECLARE @Current DATETIME
DECLARE @Last DATETIME
DECLARE @Change bit
OPEN timeLoop

FETCH NEXT FROM timeLoop into @ID,@Current
SET @LAST = DATEADD(-1,DY,@Current)

WHILE @FETCH_STATUS = 0
BEGIN
    IF ABS(DATEDIFF(h,@Last,@Current) >= 1) SET @Change = 1
    ELSE SET @Change = 0

    SELECT @Id,@Dt,@Change
    SET @Last = @Current

    FETCH NEXT FROM timeLoop into @ID,@Current
END

CLOSE timeLoop
DEALLOCATE timeLoop
对于上述任何语法错误,我们深表歉意-我在此框上没有sql server,也没有验证确切的语法,但这将助您一臂之力。 实际上,我认为您根本不需要CTE
SELECT a.ID,a.DT,ISNULL(b.DT,\'1/1/1970\')
    CASE     WHEN ABS(DATEDIFF(h,a.dt,\'1/1/1970\')) < 1 THEN 1 
            DEFAULT 1 
    END AS Change
FROM @Test a
LEFT JOIN @Test b
    ON a.ID = b.ID-1
在左连接处将表以ID-1的ID联接到自身(并听DBA的尖叫声),第一行将连接为null,随后的每一行将连接到上一行。