2017-02-09 19 views
0

Запуск SQL Server 2016 Express.SQL Server: группа по времени datetime

У меня есть эта таблица с данными выборки:

ID Datetime2    other columns 
------------------------------------------ 
1  2017-01-14 11:00:00 ... 
1  2017-01-14 11:01:00 ... 
1  2017-01-14 11:02:00 ... 
1  2017-01-14 11:03:00 ... 
1  2017-01-14 11:10:00 ... --> 7 minutes gap 
1  2017-01-14 11:11:00 ... 
1  2017-01-14 11:20:00 ... --> 9 minutes gap 
1  2017-01-14 11:22:00 ... 
1  2017-01-14 11:24:00 ... 

Я хочу иметь такой результат

ID start    end     other columns 
----------------------------------------------------------- 
1 2017-01-14 11:00 2017-01-14 11:03 ... 
1 2017-01-14 11:10 2017-01-14 11:11 ... 
1 2017-01-14 11:20 2017-01-14 11:24 ... 

Новая группа должна меня возникает, когда мы имеем зазор 5 или Х минут или больше между текущим значением даты и времени строки и значением даты и времени следующей строки.

У меня такой запрос, но я не могу понять, где группировать строки, когда у него есть пробел 5 минут и более.

WITH groups(DateTimeField, grp) AS 
(
    SELECT DISTINCT 
     DateTimeField, 
     DATEDIFF(MINUTE, DateTimeField, lag(DateTimeField) OVER (ORDER BY DateTimeField DESC)) grp 
    FROM 
     MyTable 
    WHERE 
     ID = 1 
) 
SELECT 
    COUNT(*) AS consecutiveDates, 
    MIN(DateTimeField) AS minDate, 
    MAX(DateTimeField) AS maxDate 
FROM 
    groups 
GROUP BY 
    grp 
ORDER BY 
    1 DESC, 2 DESC 

С наилучшими пожеланиями,

+1

Возможный дубликат [Групповые записи по датам подряд, когда сроки не совсем последовательным] (HTTP: // StackOverflow .com/questions/41721245/group-records-by-последовательные-даты-когда-даты-не-точно-последовательные) – GurV

+0

Возможно, вы можете использовать функцию LAG() для идентификации записей, в которых предыдущая запись была больше 5 минут. Это даст вам цели для перерывов. –

ответ

1

Во-первых, для тестирования я породившей некоторые случайные даты:

DECLARE @DatesTables TABLE (ID INT, [DateTime2] DATETIME) 

DECLARE @ID INT 
DECLARE @Date DATETIME 
SET @Date = GETDATE() 

WHILE (SELECT COUNT(*) FROM @DatesTables) < 50 
BEGIN 
    SET @ID = (SELECT COUNT(*) FROM @DatesTables) + 1 
    SET @Date = DATEADD(MINUTE, rand() * 7 + 1,@Date) 
    INSERT INTO @DatesTables (ID, [DateTime2]) VALUES (@ID, @Date) 
END 

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

DECLARE @DatesTables2 TABLE ([NewID] INT, [DateA] DATETIME, [DateB] DATETIME, DiffMin INT, [Break] INT) 

INSERT INTO @DatesTables2 
SELECT 
    ROW_NUMBER() OVER (ORDER BY a.ID), 
    a.DateTime2 AS DateA, 
    b.DateTime2 AS DateB, 
    DATEDIFF(MINUTE, a.[DateTime2], b.[DateTime2]) AS DiffMin, 
    CASE WHEN DATEDIFF(MINUTE, a.[DateTime2], b.[DateTime2]) > 5 THEN 1 ELSE 0 END AS [Break] 
FROM @DatesTables a JOIN @DatesTables b ON a.id = b.ID - 1 

Присвойте каждой строке группу, суммируя количество разрывов:

DECLARE @Groups TABLE (DateA DATETIME, DateB DATETIME, DiffMin INT, [Break] INT, [Group] INT) 

INSERT INTO @Groups 
SELECT a.DateA, a.DateB,a.DiffMin, a.[Break], SUM(b.[Break]) + a.[Break] AS [Group] FROM @DatesTables2 a JOIN @DatesTables2 b 
ON b.newid < a.newid 
GROUP BY a.DateA, a.DateB, a.[Break],a.DiffMin 

Наконец выберите сгруппированных результаты:

SELECT [Group], MIN(DateA) AS Start, MAX(DateB) AS [End] FROM @Groups GROUP BY [Group] ORDER BY [Group] 

В то время как я использовал таблицы переменных для облегчения понимания можно использовать подзапросы.

0

Благодаря @apc. Пересмотрен код для добавления функции задержки вместо соединения и удалены строки, где [Break] <> 0

//.. 
--use of the lag function 

INSERT INTO @DatesTables2 
SELECT 
    ROW_NUMBER() OVER (ORDER BY a.DateTime2 DESC), 
    a.DateTime2 AS DateA, 
    lag(DateTime2) OVER (ORDER BY DateTime2 DESC) AS DateB, 
    DATEDIFF(MINUTE, a.DateTime2 , lag(DateTime2) OVER (ORDER BY DateTime2 DESC)) AS DiffMin, 
    CASE WHEN DATEDIFF(MINUTE, a.DateTime2 , lag(DateTime2) OVER (ORDER BY DateTime2 DESC)) > 5 THEN 1 ELSE 0 END AS [Break] 
FROM DatesTables a 

//.. 
--Query only where [Break=0] to discard the end value where the gap is more than 5 minutes. 

INSERT INTO @Groups 
SELECT a.DateA, a.DateB, a.DiffMin, a.[Break], SUM(b.[Break]) + a.[Break] AS [Group] 
FROM @DatesTables2 a JOIN @DatesTables2 b ON b.newid < a.newid 
WHERE a.[Break] = 0 
GROUP BY a.DateA, a.DateB, a.[Break], a.DiffMin 

//.. 
--Finally get the datetime diff between min and max. 

SELECT [Group], MIN(DateA) AS Start, MAX(DateB) AS [End], DATEDIFF(MINUTE, MIN(DateA), MAX(DateB)) 
FROM @Groups 
GROUP BY [Group] 
ORDER BY [Group] 
+0

Стоит отметить, что LAG доступен только с SQL 2012, к сожалению, весь мой SQL должен быть совместим с 2005 годом, поэтому я никогда не использовал его. – apc

 Смежные вопросы

  • Нет связанных вопросов^_^