2012-05-12 2 views
4

У меня есть таблица вроде этого:Как я могу объединить перекрывающиеся времена в окне?

CREATE TABLE #TEMP (Name VARCHAR(255), START_TIME datetime, END_TIME datetime); 

INSERT INTO #TEMP VALUES('John', '2012-01-01 09:00:01', '2012-01-01 12:00:02') 
INSERT INTO #TEMP VALUES('John', '2012-01-01 09:40:01', '2012-01-01 11:00:02') 
INSERT INTO #TEMP VALUES('John', '2012-01-02 05:00:01', '2012-01-02 05:15:02') 
INSERT INTO #TEMP VALUES('David', '2012-01-04 05:00:01', '2012-01-04 05:15:02') 
INSERT INTO #TEMP VALUES('David', '2012-01-05 07:01:01', '2012-01-05 15:15:02') 

SELECT * 
FROM #TEMP 

DROP TABLE #TEMP 

И данные:

 Name START_TIME     END_TIME 
1 John 2012-01-01 09:00:01.000 2012-01-01 12:00:02.000 
2 John 2012-01-01 09:40:01.000 2012-01-01 11:00:02.000 
3 John 2012-01-02 05:00:01.000 2012-01-02 05:15:02.000 
4 David 2012-01-04 05:00:01.000 2012-01-04 05:15:02.000 
5 David 2012-01-05 07:01:01.000 2012-01-05 08:15:02.000 

Учитывая ряд говорят, 6, я пытаюсь сделать GROUP BY на эту таблицу и слейте раз, которые перекрываются в течение 6 часов до и после. Таким образом, в приведенной выше таблице, строки 1 и 2 будут объединены в одну строку, поскольку они содержат перекрывающиеся временной диапазон:

John 2012-01-01 06:00:01.000 2012-01-01 18:00:02.000 

Ряды 4 и 5 будут объединены, потому что вычитание 6 часов от 07:01:01.000 падает в окно ряд 4.

Есть ли хороший способ сделать это на большом столе, содержащем около миллиона строк?

+0

Я думаю, что у вас есть ошибка в тексте anwer. Когда вы говорите, что строка 1 становится до 06: 00: 01.000 - 18: 00: 02.000 не 03: 00: 01.000 - 18: 00: 02.000? (09:00 - 6 часов = 03:00, а не 06:00) – danihp

ответ

2

Я думаю, что лучший способ сделать это создает windows таблицу и присоединиться #temp таблицы с новым окном таблицей:

1) Шаг 1, подготовка таблицы окна со всеми возможными зазорами окна (содержит перекрывающиеся окна):

SELECT 
     Name, 
     dateadd(hour, -6, start_time) as start_w, 
     dateadd(hour, +6, start_time) as end_w 
    into #possible_windows 
    FROM #TEMP 

2) Создание индекса на временную таблицу для повышения производительности

create index pw_idx on #possible_windows (Name, start_w) 

3) Устранение перекрывающихся окон в автообъединение Селе кт. Это является причиной для создания индекса:

select p2.* 
    into #myWindows 
    from #possible_windows p1 
    right outer join #possible_windows p2 
    on p1.name = p2.name and 
     p2.start_w > p1.start_W and p2.start_w <= p1.end_w 
    where p1.name is null 

4) Объединить таблицу с #myWindows или использовать его непосредственно.

РАБОЧАЯ:

SELECT 
    Name, 
    dateadd(hour, -6, start_time) as start_w, 
    dateadd(hour, +6, start_time) as end_w, 
    ROW_NUMBER() over(partition by Name order by Name, 
        dateadd(hour, -6, start_time)) as rn 
into #possible_windows 
FROM #TEMP 

create index pw_idx on #possible_windows (Name, start_w) 

select p2.* 
from #possible_windows p1 
right outer join #possible_windows p2 
    on p1.name = p2.name and 
    p2.start_w > p1.start_W and p2.start_w <= p1.end_w 
where p1.name is null 

РЕЗУЛЬТАТЫ:

Name start_w  end_w   rn 
----- ------------- ------------- -- 
David 2012-01-03 23:00:012012-01-04 11:00:011 
David 2012-01-05 01:01:012012-01-05 13:01:012 
John 2012-01-01 03:00:012012-01-01 15:00:011 
John 2012-01-01 23:00:012012-01-02 11:00:013 

PE: Пожалуйста, вернитесь с вашими тестами производительности!

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