2009-06-22 2 views
6

Я следующий набор дат (дд/мм/гггг), соответствующих событий в моей базе данных:Вычислить диапазоны отсутствует дата и перекрывающиеся диапазоны дат между двумя датами

 
eventId  startDate  endDate 
1   02/05/2009 10/05/2009 
2   08/05/2009 12/05/2009 
3   10/05/2009 12/05/2009 
4   21/05/2009 21/05/2009 
5   25/05/2009 NULL 
6   01/06/2009 03/06/2009 

события имеют начальную и конечную дату (раз не имеет значения), а NULL endDate означает, что событие все еще продолжается.

То, что я хотел бы определить, - это диапазоны дат между двумя произвольными датами, когда было а) нет события, и б) события перекрывались.

Так для диапазона дат ввода от 01/04/2009 - 30/06/2009 Я хотел бы ожидать, чтобы иметь следующие результаты:

 
no event: 01/04/2009 - 01/05/2009 
overlap : 08/05/2009 - 10/05/2009 
overlap : 10/05/2009 - 12/05/2009 
no event: 13/05/2009 - 20/05/2009 
no event: 22/05/2009 - 24/05/2009 
overlap : 01/06/2009 - 03/06/2009 

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

Может ли кто-нибудь помочь мне с алгоритмом SQL для генерации этого набора результатов?

EDIT: база данных целевой платформы - это SQL Server 2005. Даты записываются как 10/05/2009 00:00:00, что означает, что событие закончилось с 10/5/2009 00:00:00 и 05.10.2009 23:59:59. То же самое относится к датам начала. Поэтому диапазон дат ввода также можно прочитать как 01/04/2009 00:00:00 - 30/06/2009 23:59:59.

+1

, на какой платформе базы данных (ы) вы будете выполняющей этот запрос? –

ответ

4

Это небольшое изменение функции выравниваться пересекающиеся timespans в SQL Server:

Это один из тех редких случаев, когда курсор-ориентированный подход в SQL Server быстрее А на основе набора:


CREATE FUNCTION mytable(@p_from DATETIME, @p_till DATETIME) 
RETURNS @t TABLE 
     (
     q_type VARCHAR(20) NOT NULL, 
     q_start DATETIME NOT NULL, 
     q_end DATETIME NOT NULL 
     ) 
AS 
BEGIN 
     DECLARE @qs DATETIME 
     DECLARE @qe DATETIME 
     DECLARE @ms DATETIME 
     DECLARE @me DATETIME 
     DECLARE cr_span CURSOR FAST_FORWARD 
     FOR 
     SELECT startDate, endDate 
     FROM mytable 
     WHERE startDate BETWEEN @p_from AND @p_till 
     ORDER BY 
       startDate 
     OPEN cr_span 
     FETCH NEXT 
     FROM cr_span 
     INTO @qs, @qe 
     SET @ms = @qs 
     SET @me = @qe 
     WHILE @@FETCH_STATUS = 0 
     BEGIN 
       FETCH NEXT 
       FROM cr_span 
       INTO @qs, @qe 
       IF @qs > @me 
       BEGIN 
         INSERT 
         INTO @t 
         VALUES ('overlap', @ms, @me) 
         INSERT 
         INTO @t 
         VALUES ('gap', @me, @qs) 
         SET @ms = @qs 
       END 
       SET @me = CASE WHEN @qe > @me THEN @qe ELSE @me END 
     END 
     IF @ms IS NOT NULL 
     BEGIN 
       INSERT 
       INTO @t 
       VALUES (@ms, @me) 
     END 
     CLOSE cr_span 
     RETURN 
END 
GO 

Эта функция сжимает каждый непрерывный набор пересекающихся диапазонов в один диапазон и возвращает как диапазон, так и следующий пробел.

+0

Является ли ответ Quassnoi решением проблемы? если да, то каково имя таблицы данных в функции. – 2009-09-08 06:36:43

+0

+1 Спасибо ....... –

1

не понимая, что проблема, которую вы пытаетесь решить, вот мое решение некоторые проблемы с верхней части моей головы:

  1. Создать таблицу функций (UDF) «все-дат», которые будут вернуть все даты в год.
  2. Конвертировать ваши события в отдельные даты (одна строка событий будет иметь столько строк, сколько есть дни в ней) путем сопутствующих событий на все даты where the date is between event's start and end dates ... Сохранять исходное событие.
  3. Сделайте внешнее соединение дат с датами (опять же), чтобы найти пробелы или промахи.
  4. Соедините даты с самим собой по номеру where dates are same but eventId is not, чтобы найти перекрытия.
0

мои бедные, с PostgreSQL, вы можете сделать это просто:

дает Это выражение (start1, end1) перекрывается (start2, end2) (start1, length1) перекрывается (start2, Length2)

true, когда два периода времени (определенные их конечными точками) перекрываются, ложные, когда они не перекрываются. Конечные точки могут быть указаны как пары дат, времени или временных меток; или как дата, время или отметка времени с последующим интервалом.

SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Результат: true SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Результат: ложные

но под SQL Server, я не знаю ... жаль

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