SQL: Как группировать с интервалом в 30 секунд и отмечать максимальное время в этой группе? - PullRequest
0 голосов
/ 29 июня 2018

У меня есть следующая таблица:

CREATE TABLE #times
(
num int,
atime datetime    
)

 INSERT #times VALUES (1, '8/27/2015 1:10:00');
 INSERT #times VALUES (1, '8/27/2015 1:10:15'); 
 INSERT #times VALUES (1, '8/27/2015 1:10:28' );
 INSERT #times VALUES (2, '7/3/2018 2:20:50' );
 INSERT #times VALUES (2, '7/3/2018 2:21:05' );
 INSERT #times VALUES (2, '7/3/2018 2:21:10' );
 INSERT #times VALUES (2, '7/3/2018 2:30:55' );
 INSERT #times VALUES (3, '1/1/2018 10:20:25');
 INSERT #times VALUES (4, '1/1/2018 10:20:05');
 INSERT #times VALUES (5, '9/15/2015 2:20:55');

Я бы хотел сгруппировать по num и atime в течение 30-секундного интервала, затем отметить максимальное время с 0 и другие времена в группе с 1.

Таким образом, результирующий набор данных будет таким:

1 '8/27/2015 1:10:00' 1 
1 '8/27/2015 1:10:15' 1
1 '8/27/2015 1:10:28' 0   <<this is the max time of the grouping within num and 30 secs
2 '7/3/2018 2:20:50'  1
2 '7/3/2018 2:21:05'  1
2 '7/3/2018 2:21:10'  0   <<this is the max time of the grouping within num and 30 secs
2 '7/3/2018 2:30:55'  0
3 '1/1/2018 10:20:25' 0
4 '1/1/2018 10:20:05' 0
5 '9/15/2015 2:20:55' 0

Ответы [ 4 ]

0 голосов
/ 29 июня 2018

Я считаю, что другие ответы слишком сложны. По сути, вы хотите пометить строки, где следующий раз больше, чем 30 секунд.

Это легко, используя lead():

select t.*,
       (case when lead(atime) over (partition by num order by atime) < dateadd(second, 30, atime)
             then 1
             else 0
        end) as flag
from #times t;

Здесь - это скрипта SQL.

0 голосов
/ 29 июня 2018

Не уверен, что я понял 100%, но посмотрите на это, посмотрите, поможет ли это.

WITH    cte
            AS (SELECT    *
                ,         CAST(atime AS DATE) D
                ,         DATEPART(HOUR, atime) H
                ,         DATEPART(MINUTE, atime) M
                ,         CASE WHEN DATEPART(SECOND, atime) < 30 THEN 0
                                ELSE 30
                        END AS S
                FROM      #times
                ),
        cte2
            AS (SELECT    *
                ,         ROW_NUMBER() OVER (PARTITION BY num, D, H, M, S ORDER BY atime DESC) RN
                FROM      cte
                )
    SELECT  cte2.num
     ,      cte2.atime
     ,      CASE cte2.RN WHEN 1 THEN 0 ELSE 1 END
    FROM    cte2
    ORDER BY atime
0 голосов
/ 29 июня 2018

Вот, пожалуйста:

;with stats1(num,mintime) as(
    select num,min(atime) mintime
    from #times t1
    group by num
),
stats2(num,maxtime) as(
    select s1.num,max(t.atime) maxtime
    from stats1 s1
    inner join #times t on s1.num=t.num
    where t.atime<=dateadd(second,30,s1.mintime)
    group by s1.num
)
select t.num, t.atime, case when t.atime>=s2.maxtime then 0 else 1 end
from stats2 s2
inner join #times t on s2.num=t.num
0 голосов
/ 29 июня 2018

Попробуйте выбрать нужные строки

SELECT DISTINCT num,
    MAX(atime) OVER(PARTITION BY num) AS maxAtime
FROM #times
WHERE DATEPART(SECOND, atime) <= 30

Или это, чтобы отметить строки

SELECT num, atime, IIF(atime = sub.maxAtime, 1, 0) AS flagged
FROM (
    SELECT num,
        atime,
        MAX(atime) OVER(PARTITION BY num) AS maxAtime
    FROM #times
    WHERE DATEPART(SECOND, atime) <= 30
) AS sub;
...