Переменное значение столбца на основе столбца даты и времени в T-SQL Query - PullRequest
1 голос
/ 14 июня 2011

Извиняюсь за ужасный заголовок, не совсем уверен, как объяснить это без образца:

Я пытаюсь вернуть столбец в запросе, чередующийся от 0 до 1 в качестве часа столбца datetimeнад результирующим набором изменений. У кого-нибудь есть предложения о том, как это сделать?ИЛИ как это можно сделать с помощью 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] чередовался, когда дата и время в строках меняются на новые часы.Будь то следующий час в тот же день или другой час следующего дня.

Ответы [ 2 ]

5 голосов
/ 14 июня 2011

Как насчет?

SELECT *, 
    (dense_rank() over (order by Dateadd(hh,Datediff(hh,0,dt),0))) % 2 as [band]
FROM @test

У меня сейчас нет под рукой sql. Но

  1. dateadd / datediff очищает минуты от часов
  2. Затем DRA__RANK заказывает их как число, но не нумерует дубликаты
  3. тогда% 2 делает то, что вы делали в исходном запросе.
2 голосов
/ 14 июня 2011

Как я понимаю, вопрос:

Вы хотите сравнить значение даты и времени каждой записи с предыдущей записью, и если час или любое значение, превышающее час, изменилось, верните 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 на этом поле и я не проверил точный синтаксис, но это поможет вам.

На самом деле я не думаю, что вам вообще нужен CTE

SELECT a.ID, a.DT, ISNULL(b.DT, '1/1/1970')
    CASE     WHEN ABS(DATEDIFF(h, a.dt, ISNULL(b.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 (и прослушайте крик DBA) при левом соединении,и первая строка присоединится к нулю, каждая последующая строка присоединится к предыдущей строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...