SQL Server 2008 Генерация серии дат и времени - PullRequest
14 голосов
/ 22 августа 2011

Я пытаюсь сгенерировать таблицу с серией значений времени в ней.

У меня есть заданные время начальной даты и время конечной даты (время окончания даты - конец последовательности), я добавляю времяинтервал ~ (это может варьироваться) до времени начала даты в секундах, и это дает мне время окончания даты.

Следующая последовательность использует время окончания даты в качестве начального значения и добавляет к нему временной интервал в секундах.Чтобы продемонстрировать вывод мне нужно.Есть ли быстрый способ создать такую ​​таблицу, кроме использования большого количества вставок в команды? Я действительно озадачен

StartTime               Endtime                 Duration
2011-07-20 11:00:33     2011-07-20 11:09:47     554
2011-07-20 11:09:47     2011-07-20 11:19:01     554

    declare @StartTime datetime = '2011-07-20 11:00:33',
    @EndTime datetime = '2011-07-20 15:37:34'
    @Interval int = 554 -- this can be changed.

    insert into tmp_IRange
    values('2011-07-20 11:00:33', DATEADD(SECONDS, @Duration, 2011-07-20 11:00:33))

, это становится очень утомительным, особенно когда время окончания даты * 1008.* нужно сделать много операторов вставки: (

Ответы [ 6 ]

19 голосов
/ 22 августа 2011

Использовать рекурсивный CTE

declare @StartTime datetime = '2011-07-20 11:00:33',
    @EndTime datetime = '2011-07-20 15:37:34',
    @Interval int = 554 -- this can be changed.

;WITH cSequence AS
(
    SELECT
       @StartTime AS StartRange, 
       DATEADD(SECOND, @Interval, @StartTime) AS EndRange
    UNION ALL
    SELECT
      EndRange, 
      DATEADD(SECOND, @Interval, EndRange)
    FROM cSequence 
    WHERE DATEADD(SECOND, @Interval, EndRange) < @EndTime
)
 /* insert into tmp_IRange */
SELECT * FROM cSequence OPTION (MAXRECURSION 0);
5 голосов
/ 22 августа 2011

Это даст отдельные диапазоны, но будет игнорировать ваше фактическое время окончания (так как оно <@interval после последнего действительного диапазона): </p>

;WITH x AS 
(
    SELECT TOP (DATEDIFF(SECOND, @StartTime, @EndTime)/@Interval) 
        rn = ROW_NUMBER() OVER (ORDER BY [object_id])
    FROM sys.objects
)
-- INSERT INTO dbo.tmp_IRange
SELECT DATEADD(SECOND, @Interval * (rn-1), @StartTime),
    DATEADD(SECOND, @Interval * rn, @StartTime)
FROM x;
4 голосов
/ 22 августа 2011

Это должно помочь вам начать.Вы можете адаптировать его к вашим конкретным потребностям.Как написано, он будет генерировать строку для каждого приращения минуты, начиная с текущей даты и времени.

DECLARE @BaseDate DateTime = GETDATE();

WITH DateTable (DateValue) AS (
    SELECT @BaseDate DateValue
    UNION ALL
    SELECT DATEADD(Minute, 1, DateValue) DateValue
    FROM DateTable
)
SELECT *
FROM DateTable
WHERE DateValue < DATEADD(Day, 1, GETDATE())
OPTION (MAXRECURSION 0);
3 голосов
/ 22 августа 2011

Вот еще одно нерекурсивное решение на основе множеств, в котором используется системная таблица с именем master..spt_values:

DECLARE
  @StartTime datetime = '2011-07-20 11:00:33',
  @EndTime datetime = '2011-07-20 15:37:34',
  @Interval int = 554;
SELECT
  StartTime = DATEADD(SECOND, (number - 1) * @Interval, @StartTime),
  EndTime   = DATEADD(SECOND, (number - 0) * @Interval, @StartTime),
  Duration  = @Interval
FROM master..spt_values
WHERE type = 'P'
  AND number BETWEEN 1 AND DATEDIFF(SECOND, @StartTime, @Endtime) / @Interval

UNION ALL

SELECT
  DATEADD(SECOND, -Duration, EndTime),
  EndTime,
  Duration
FROM (
  SELECT
    EndTime = @EndTime,
    Duration = DATEDIFF(SECOND, @StartTime, @Endtime) % @Interval
) s
WHERE Duration > 0

Первый SELECT генерирует набор строк, состоящий из коротких интервалов указанной длины, которые лежат в указанном диапазоне. При необходимости второй SELECT добавляет интервал между временем окончания последнего интервала первого SELECT и указанным временем окончания.

Подмножество master..spt_values, которое особенно используется здесь (и может использоваться во многих подобных случаях), предоставляет список чисел от 0 до 2047. Это означает, что вы не сможете использовать это решение с таблица, если начальный интервал будет разбит на более чем 2047 коротких (er) интервалов. Затем вы должны подумать о чем-то вроде вашей таблицы чисел .

0 голосов
/ 22 августа 2011

пожалуйста, попробуйте этот код:

create table #T (date_begin datetime, date_end datetime)    

declare @StartTime datetime = '2011-07-20 11:00:33',
    @EndTime datetime = '2011-07-20 15:37:34',
    @Interval int = 554 -- this can be changed.

while DATEADD(ss,@Interval,@StartTime)<=@EndTime
begin
    insert #T
    select @StartTime, DATEADD(ss,@Interval,@StartTime)

    set @StartTime = DATEADD(ss,@Interval,@StartTime)
end


select * from #T
0 голосов
/ 22 августа 2011

Надеюсь, это поможет ...

declare @StartTime datetime = '2011-07-20 11:00:33',
@EndTime datetime = '2011-07-20 11:00:33',
@Interval int = 554,

@LimitTime datetime = '2011-07-20 15:37:34'

WHILE @EndTime < @LimitTime
BEGIN
SELECT @EndTime = DATEADD(S, @Interval, @StartTime)

SELECT @StartTime, @EndTime
--INSERT INTO tmp_IRange VALUES(@StartTime, @EndTime)

SELECT @StartTime = @EndTime

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