2016-08-04 3 views
0

У меня есть таблица с записями в TimeLines, мне нужно получить строки, которые образуют цепочку из 45 минут.выберите цепочку записей, используя mssql

1|2016-01-01 00:00 
2|2016-01-01 00:30 
3|2016-01-01 00:45 
4|2016-01-01 01:00 

Как я могу найти 2-ю строку в зависимости от этого времени, причины 2-й, 3-й и 4-й ряды неразрывны 15 минут цепь график для 45 мин набора? 1-й и 2-й не совсем нормально, поэтому интервал между таймингами составляет 30 мин.

2-я, 3-я и 4-я строки являются последовательной цепочкой временной шкалы. 2-й ряд плюс 15 минут - хорошо. причина существовала 3-я строка с этим временем. 3-й ряд плюс 15 минут - хорошо. причина существовала 4-я строка с этим временем. Как результат, у меня есть постоянная цепочка времени на 45 минут.

1row plus 15 min - не в порядке. причина 00:15 время с датой не было.

+1

Вопрос не ясен. Что вы подразумеваете под ** цепочкой **? Только две строки или может быть много таких строк? Предоставьте более четкое описание того, что вам нужно. – FDavidov

+0

Извините, позвольте мне объяснить. 2-я, 3-я и 4-я строки являются последовательной цепочкой временной шкалы. 2-й ряд плюс 15 минут - хорошо. за это время существовала 3-я строка. 3-й ряд плюс 15 минут - хорошо. за это время существовала 4-я строка. 1-рядный плюс 15 минут - не в порядке. причина 00:15 время с датой не было. –

+0

С какой версией SQL Server вы работаете? –

ответ

0

Попробуйте

DECLARE @Tbl TABLE (Id INT, StartDate DATETIME) 
INSERT INTO @Tbl 
VALUES 
(1,'2016-01-01 00:00'), 
(2,'2016-01-01 00:30'), 
(3,'2016-01-01 00:45'), 
(4,'2016-01-01 01:00') 


;WITH CTE 
AS 
(
    SELECT 
     Id , 
     StartDate, 
     ROW_NUMBER() OVER (ORDER BY Id) AS RowId 
    FROM 
    @Tbl 
) 


SELECT 
    CurRow.*, 
    CASE 
     WHEN 
      DATEDIFF(MINUTE, CurRow.StartDate, NextRow.StartDate) = 15 OR 
      DATEDIFF(MINUTE, PrevRow.StartDate, CurRow.StartDate) = 15 
      THEN '15 MIN' 
     ELSE 'NO' END Flag 
FROM 
    CTE CurRow LEFT JOIN 
    (SELECT *, C.RowId - 1 AS TmpRowId FROM CTE C) NextRow ON CurRow.RowId = NextRow.TmpRowId LEFT JOIN 
    (SELECT *, C.RowId + 1 AS TmpRowId FROM CTE C) PrevRow ON CurRow.RowId = PrevRow.TmpRowId 

ВЫВОД:

Id StartDate     RowId Flag 
1 2016-01-01 00:00:00.000  1  NO 
2 2016-01-01 00:30:00.000  2  15 MIN 
3 2016-01-01 00:45:00.000  3  15 MIN 
4 2016-01-01 01:00:00.000  4  15 MIN 
0

Если я вас правильно понимаю, вы можете использовать LEAD/LAG:

WITH Src AS 
(
    SELECT * FROM (VALUES 
    (1,'2016-01-01 00:00'), 
    (2,'2016-01-01 00:30'), 
    (3,'2016-01-01 00:45'), 
    (4,'2016-01-01 01:00')) T(ID, [Date]) 
) 
SELECT *, CASE WHEN LEAD([Date]) OVER (ORDER BY ID)=DATEADD(MINUTE, 15, [Date]) 
       OR LAG([Date]) OVER (ORDER BY ID)=DATEADD(MINUTE, -15, [Date]) 
       THEN 'Chained' END [Status] 
FROM Src 

Он производит:

ID Date    Status 
-- ----    ------ 
1 2016-01-01 00:00 NULL 
2 2016-01-01 00:30 Chained 
3 2016-01-01 00:45 Chained 
4 2016-01-01 01:00 Chained 
+1

Примечание: Это будет работать только для версий 2012 или выше. –

0

Вы можете сделать это с OUTER APPLY и хитрым ROW_NUMBER():

;WITH TimeLines AS ( --This CTE is similar to your table 
SELECT * 
FROM (VALUES 
(1, '2016-01-01 00:00'),(2, '2016-01-01 00:30'), 
(3, '2016-01-01 00:45'),(4, '2016-01-01 01:00'), 
(5, '2016-01-01 01:05'),(6, '2016-01-01 01:07'), 
(7, '2016-01-01 01:15'),(8, '2016-01-01 01:30'), 
(9, '2016-01-01 01:45'),(10, '2016-01-01 02:00') 
) as t(id, datum) 
) 
, cte AS (
SELECT t.id, 
     t.datum, 
     CASE WHEN ISNULL(DATEDIFF(MINUTE,t1.datum,t.datum),0) != 15 THEN DATEDIFF(MINUTE,t.datum,t2.datum) ELSE 15 END as i 
FROM TimeLines t --in this cte with the help of 
OUTER APPLY ( --OUTER APPLY we are getting next and previous dates to compare them 
    SELECT TOP 1 * 
    FROM TimeLines 
    WHERE t.datum > datum 
    ORDER BY datum desc) t1 
OUTER APPLY (
    SELECT TOP 1 * 
    FROM TimeLines 
    WHERE t.datum < datum 
    ORDER BY datum asc) t2 
) 

SELECT *, --this is final select to get rows you need with chaines 
     (ROW_NUMBER() OVER (ORDER BY (SELECT 1))+2)/3 as seq 
FROM cte 
WHERE i = 15 

Выход:

id datum    i seq 
2 2016-01-01 00:30 15 1 
3 2016-01-01 00:45 15 1 
4 2016-01-01 01:00 15 1 
7 2016-01-01 01:15 15 2 
8 2016-01-01 01:30 15 2 
9 2016-01-01 01:45 15 2 
10 2016-01-01 02:00 15 3