2015-07-15 4 views
2

Необходимо подсчитывать количество раз, когда пара объектов отображается вместе в течение заданного интервала времени. Улов есть, если один и тот же объект указан несколько раз в течение 5-минутного промежутка, который должен считаться одним из случаев. У меня есть код для подсчета каждых отдельных пару вхождений, но не могу понять, как группировать несколько вхождений появляться в течение 5 минут:Группировка строк по временному диапазону

if object_id(N'a', N'U') IS NOT NULL 
    DROP TABLE a; 
GO 

create table a (name varchar (20), dt datetime); 
go 

create index i1 on a (name); 

insert a 
values 
    ('A', '20140101 13:00:00.000') 
, ('A', '20140101 13:00:01.000') 
, ('A', '20140101 13:00:02.000') 
, ('B', '20140101 13:01:00.000') 
, ('C', '20140101 13:01:30.000') 
, ('D', '20140101 13:02:00.000') 
, ('E', '20140101 13:02:30.000') 

, ('B', '20140201 13:00:00.000') 
, ('C', '20140201 13:01:00.000') 
, ('K', '20140201 13:01:30.000') 
, ('L', '20140201 13:02:00.000') 
, ('M', '20140201 13:02:30.000') 
, ('A', '20140201 13:03:00.000') 

, ('A', '20140301 13:00:00.000') 
, ('D', '20140301 13:01:00.000') 
, ('E', '20140301 13:01:30.000') 
, ('P', '20140301 13:02:00.000') 
, ('R', '20140301 13:02:30.000') 
, ('Q', '20140301 13:03:00.000') 

, ('A', '20140401 13:00:00.000') 
, ('X', '20140401 13:01:00.000') 
, ('Y', '20140401 13:01:30.000') 
, ('Z', '20140401 13:02:00.000') 
GO 

with prox (FirstName, SecondName) 
    AS (select a.name, b.name 
     from a 
     cross join a AS b 
     where a.name < b.name 
     and ABS(DATEDIFF(mi, a.dt, b.dt)) < 5) 

select FirstName, SecondName, count(*) 
from prox 
group by FirstName, SecondName 
having count(*) > 1 
order by 1, 2 

В моем примере счетчик для AB, AC, AD и AE должен быть 2 не 4, потому что в первой группе А появилась 3 раза в течение 5 минут, которая должна отсчитываться один раз не 3 раза.

+1

'случай, когда 0 = COUNT(), то 0 еще 1 конец '? –

+1

Это только 0 - 5, 5 - 10, 10 - 15 или любой 5-минутный период? И если это какой-то 5-минутный период, как решить, какая группа 5 минут, если есть несколько событий, например, за 7 минут? –

+0

5 минут промежуток из другой сопоставив объект. –

ответ

1

вы можете создать еще один КТР, чтобы получить только значения, по крайней мере, 5 минут врозь первым затем использовать ваш CTE

WITH cte 
    AS (SELECT 
      name, 
      dt 
     FROM 
      a a1 
     WHERE 
      dt = (SELECT MIN (dt) FROM a a2 WHERE a2.name = a1.name 
       ) 
     UNION ALL 
     SELECT 
      a1.name, 
      a1.dt 
     FROM 
      a a1 
     JOIN cte a2 ON a1.name = a2.name 
         AND a1.dt > DATEADD(minute,5,a2.dt) 
     ), 
cteGroup 
    AS (SELECT DISTINCT 
      name, 
      dt 
     FROM 
      cte 
    ), 

prox(FirstName,SecondName) 
    AS (SELECT 
      a.name, 
      b.name 
     FROM 
      cteGroup AS a 
     CROSS JOIN cteGroup AS b 
     WHERE 
      a.name < b.name 
      AND ABS(DATEDIFF(mi,a.dt,b.dt)) < 5 
     ) 
SELECT 
    FirstName, 
    SecondName, 
    COUNT(*) 
FROM 
    prox 
GROUP BY 
    FirstName, 
    SecondName 
HAVING 
    COUNT(*) > 1 
ORDER BY 
    1, 
    2 

SQL Fiddle

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