2010-02-02 3 views
1

Нужна помощь в создании запроса для этого.TSQL: значения перекрытия и интервалов времени и времени

Start    | End 
2009-01-01 06:00:00 | 2009-01-01 14:00:00 
2009-01-01 06:00:00 | 2009-01-02 06:00:00 
2009-01-02 07:00:00 | 2009-01-02 08:00:00 
2009-01-03 06:00:00 | 2009-01-03 14:00:00 
2009-01-03 09:00:00 | 2009-01-03 11:00:00 
2009-01-04 22:00:00 | 2009-01-05 06:00:00 
2009-01-05 01:00:00 | 2009-01-05 10:00:00 

Я хотел бы получить не-перекрывающееся время для интервала (2009-01-01 00:00:00 - 2009-01-31 00:00:00) с суммой за каждый день, как это:

Date  | Duration 
2009-01-01 | 18 
2009-01-02 | 7 
2009-01-03 | 8 
2009-01-04 | 2 
2009-01-05 | 10 

Затем, глядя на общую сумму в целом запрошенный интервал.

Вы можете помочь построить этот запрос?

+0

Будет ли запрошенный интервал всегда начинаться и останавливаться в полночь соответствующих дней? –

+0

Да, это идея. – Solata

+0

Как зовут вашу таблицу? –

ответ

1

Попробуйте это:

WITH Times AS (
     SELECT DISTINCT(Start) AS Time FROM intervals 
     UNION ALL 
     SELECT DISTINCT([End]) AS Time FROM intervals), 
    Days AS (SELECT DISTINCT DATEADD(dd, 0, DATEDIFF(dd, 0, Time)) AS Time FROM Times), 
    Times2 AS (
     SELECT Time FROM times 
     UNION ALL 
     SELECT Time FROM days), 
    Times3 AS (SELECT ROW_NUMBER() OVER (ORDER BY Time) AS rn, Time FROM Times2), 
    Times4 AS (
     SELECT T1.Time AS Start, T2.Time AS [End] 
     FROM Times3 T1 
     JOIN Times3 T2 
     ON T1.rn + 1 = T2.rn), 
    IntervalParts AS (
     SELECT DISTINCT Times4.* 
     FROM Times4 
     JOIN intervals 
     ON Times4.Start >= intervals.Start AND Times4.[End] <= intervals.[End]), 
    IntervalsByDay AS (
     SELECT 
      DATEADD(dd, 0, DATEDIFF(dd, 0, Start)) AS Day, 
      DATEDIFF(hh, Start, [End]) AS Duration 
     FROM IntervalParts) 
SELECT Day, SUM(Duration) AS Duration 
FROM IntervalsByDay 
GROUP BY Day 

Результаты:

Day      Duration 
2009-01-01 00:00:00.000 18 
2009-01-02 00:00:00.000 7 
2009-01-03 00:00:00.000 8 
2009-01-04 00:00:00.000 2 
2009-01-05 00:00:00.000 10 

Чтобы ограничить его в определенном диапазоне, просто добавьте соответствующий ИНЕКЕ.

+0

Создал tmp table @intervals и поставил @ в запросе, но получил «Msg 137, Level 15, State 2, Line 36 Должен объявить скалярную переменную« @intervals ».» В строке: «ON Times4.Start» = interval.Start AND Times4. [End] <= interval. [End]), « Любая идея, что не так? – Solata

+0

Я не понимаю, почему вы используете временные таблицы. Это кажется совершенно ненужным. Разве ваши данные в реальной таблице? –

+0

Temp предназначен для тестирования. Попробуй на настоящем столе. Имя таблицы temp - @intervals. – Solata

0

Отъезд DATEDIFF в sqlserver. Я не уверен, какой сервер db вы используете, но я полагаю, что у других RDBMS будет что-то похожее или достаточно, чтобы вы могли создать свою собственную функцию для этого.

SELECT start, DATEDIFF(hh, start, end) FROM ...... 

Похоже, что я пропустил эту часть с несколькими датами. Чтобы разделить это на несколько дней, я думаю, вам придется обрабатывать каждую запись отдельно и хранить в таблице temp или что-то в этом роде. Возможно, вы могли бы создать функцию, которая возвращает таблицу для каждой записи, которая разделяет длительности по дате, и тогда это может быть SUMMED для каждой даты.?

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