Создайте 15-минутные интервалы дат и объедините соответствующие строки - PullRequest
0 голосов
/ 26 ноября 2018

Что я хотел бы сделать, это получить 15-минутные интервалы на основе диапазона дат в строке и вставить их в другую таблицу.

Учитывая, что следующий код возвращает мне диапазон дат, который является частью моегоцель:

DECLARE @Table1 TABLE (ID INT IDENTITY(0,1), TIMEVALUE DATETIME, TIMEVALUE2 DATETIME);
DECLARE @start DATETIME2(7) = '2018-01-04 10:55:00'
DECLARE @end DATETIME2(7) = '2018-01-05 03:55:00'
SELECT  @start = dateadd(minute, datediff(minute,0,@start) / 15 * 15, 0);

WITH CTE_DT AS 
(
    SELECT @start AS DT
    UNION ALL
    SELECT DATEADD(MINUTE,15,DT) FROM CTE_DT
    WHERE DT< @end
)
INSERT INTO @Table1
SELECT DT, DATEADD(minute,14,dt) FROM CTE_DT
OPTION (MAXRECURSION 0);

SELECT * FROM @Table1    

результат:

ID  TIMEVALUE               TIMEVALUE2
0   2018-01-04 10:45:00.000 2018-01-04 10:59:00.000
1   2018-01-04 11:00:00.000 2018-01-04 11:14:00.000
2   2018-01-04 11:15:00.000 2018-01-04 11:29:00.000
3   2018-01-04 11:30:00.000 2018-01-04 11:44:00.000
4   2018-01-04 11:45:00.000 2018-01-04 11:59:00.000
5   2018-01-04 12:00:00.000 2018-01-04 12:14:00.000
6   2018-01-04 12:15:00.000 2018-01-04 12:29:00.000
7   2018-01-04 12:30:00.000 2018-01-04 12:44:00.000
8   2018-01-04 12:45:00.000 2018-01-04 12:59:00.000
..
..

Чего я хочу добиться, так это применить ту же логику, что и выше, из источника записи.

Так что, если мои SourceDatais

Col1    Col2    StartDate           EndDate
AA      AA      2018-01-01 13:25    2018-01-02 13:00
AA      BB      2018-01-02 13:25    2018-01-03 13:00

, поэтому с запросом каким-то образом используйте начало и конец для получения этого результата всего лишь запросом

Col1    Col2    TIMEVALUE       TIMEVALUE2
AA      AA  2018-01-01 13:15:00 2018-01-01 13:29:00
AA      AA  2018-01-01 13:30:00 2018-01-01 13:44:00
AA      AA  2018-01-01 13:45:00 2018-01-01 13:59:00
...
...
AA      AA  2018-01-02 12:30:00 2018-01-02 12:44:00
AA      AA  2018-01-02 12:45:00 2018-01-02 12:59:00
AA      AA  2018-01-02 13:00:00 2018-01-02 13:14:00
AA      BB  2018-01-02 13:15:00 2018-01-02 13:29:00
AA      BB  2018-01-02 13:30:00 2018-01-02 13:44:00
AA      BB  2018-01-02 13:45:00 2018-01-02 13:59:00
...
...
AA      BB  2018-01-03 12:30:00 2018-01-03 12:44:00
AA      BB  2018-01-03 12:45:00 2018-01-03 12:59:00
AA      BB  2018-01-03 13:00:00 2018-01-03 13:14:00

Я бы хотел, если смогу, использовать курсор.Мне удалось сделать эту работу с пользовательской функцией, передав необходимые столбцы с оператором select.Я надеюсь, что смогу избежать этого, если смогу.

Ответы [ 3 ]

0 голосов
/ 26 ноября 2018

Вместо использования rCTE (который является формой RBAR), я бы использовал виртуальную таблицу подсчета для генерации ваших дат:

--; is a statement terminator, not a "beginninator". It goes at the end, for the start.
WITH N AS(
    SELECT NULL AS N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS (
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1 --10
         CROSS JOIN N N2 --100
         CROSS JOIN N N3 --1000
         CROSS JOIN N N4 --10000
    )
SELECT DATEADD(MINUTE,15*I,@Start)
FROM Tally
WHERE DATEADD(MINUTE,15*I,@Start) < @End;

Если вы хотите сгенерировать 15-минутные интервалы для комбинациистолбцы, вы можете сделать еще CROSS JOIN.Например:

--Assume CTEs are already declared
SELECT V.Col1, V.Col2,
       DATEADD(MINUTE,15*T.I,@Start)
FROM Tally T
     CROSS JOIN (VALUES('AA','AA'),('AA','BB')) V(Col1, Col2) --This could be a CROSS APPLY to a DISTINCT, or similar is you wish
WHERE DATEADD(MINUTE,15*T.I,@Start) < @End;
0 голосов
/ 26 ноября 2018

Я не согласен с идеей иметь 14, 29, 44 и 59 в качестве конечных минут.Это не будет соответствовать значениям, таким как 00:14:59.9999999.Сказав это, вам нужно следующее условие соединения:

SELECT *
FROM @Table1
INNER JOIN yourdata ON TIMEVALUE2 >= StartDate AND EndDate >= TIMEVALUE

DEMO на DB Fiddle

Преобразование вышеуказанного в эксклюзивные даты окончания (15, 30, 45и 00) тривиально.Просто измените >= на >.

Демонстрация на DB Fiddle

0 голосов
/ 26 ноября 2018

Измените конец первого запроса так, чтобы вместо

SELECT * FROM @Table1  

было написано:

SELECT * FROM @Table1 d 
INNER JOIN SourceData sd 
ON NOT(d.timevalue2 < sd.startdate OR d.timevalue1 > sd.enddate)

Рассмотрите возможность принятия первого запроса, который генерирует даты, и просто запустите его длятеперь до 2030 года и вставьте даты в фактическую таблицу.Сохраняйте запрос, чтобы его можно было снова использовать через ~ 11 лет, чтобы добавить еще несколько строк в таблицу календаря

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