2010-07-06 12 views
2

Я храню некоторые интервалы в SQL, например:Проверьте интервал времени, используя SQL условие

id INT 
from DATE 
to DATE 

Как можно проверить, используя только одно условие (если это возможно), если новый интервал конфликт с существующей ?

Примеры:

|-----------| (from 1 to 5) 
    |-----------| (from 2 to 6) 
     |--| (from 3 to 4) 
        |--| (from 7 to 8) 

Каждый интервал (в первых трех) имеет некоторый конфликт с двумя другими интервалами ... За исключением последнего, что в одиночку.

-

Эта проверка может быть достигнута с помощью некоторых условий, как:

WHERE (`from` <= $FROM and `to` >= $TO) 

Но это только контрольные интервалы, которые содержит новый один ... Не другие интервалы, что имеет некоторые пересечения ИЛИ те, что внутри новый.

Возможно, что-то вроде этого?

WHERE NOT (`from` < $FROM and `to` < $TO) AND NOT (`from` > $FROM and `to` > $TO) 

Obs .: Мне нужно найти столкновения, чтобы предупредить пользователя, что этот новый период уже существует или попасть в конфликт с existin один.

+0

Какое представление периодов вы используете, например. закрытые открыть? Иными словами, считаете ли вы (от 1 до 5) 'столкновением с' (от 5 до 6) '? – onedaywhen

ответ

2
WHERE ($TO >= `from` AND $FROM <= `to`) 

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

+0

+1, классический вопрос о задании на работу :) – Konerak

+0

WTF! Ты гений! –

+0

Я работал в системах ГИС еще в 80-х годах. Пересечения и совпадения являются для меня второй натурой. –

3

Я столкнулся с этим вопросом и просто хотел попытаться показать, как таблица истинности может идентифицировать приведенную логику, которую Павел уже опубликовал.

Предположим, у вас есть интервал from [ to ], который вы хотите проверить на from { to }.

Это приводит к следующей таблице истинности:

# [ < { [ < } ] < { ] < } Collision? Example 
1  T  T  T  T   F  [ ] { } 
2  T  T  T  F   T  [ } { ] * 
3  T  T  F  T   T  [ { ] } 
4  T  T  F  F   T  [ { } ] 
5  T  F  T  T   T  ] } [ { * 
6  T  F  T  F   T  } [ ] { * 
7  T  F  F  T   Contradiction 
8  T  F  F  F   T  } [ { ] * 
9  F  T  T  T   T  ] { [ } * 
10  F  T  T  F   Contradiction 
11  F  T  F  T   T  { [ ] } 
12  F  T  F  F   T  { [ } ] 
13  F  F  T  T   T  ] { } [ * 
14  F  F  T  F   T  } ] { [ * 
15  F  F  F  T   T  { ] } [ * 
16  F  F  F  F   F  { } [ ] 

Глядя на этой таблице истинности, самое простое выражение для выявления коллизий является:

NOT ([ < { AND [ < } AND ] < { AND ] < }) AND NOT ([ >= { AND [ >= } AND ] >= { AND ] >= })

Однако мы знаем, что, так как { < } и [ < ], это сокращается до

NOT ([ < { AND ] < {) AND NOT ([ >= } AND ] >= })

что соответствует SQL:

WHERE NOT ('from' < $FROM and 'to' < $FROM) AND NOT ('from' > $TO and 'to' > $TO) (аналогично тому, что @TiuTalk предложил).

Однако мы уже предположили, что { < } и [ < ]. Это важно. Посмотрите на строки с пометкой * в таблице истинности. В этих рядах либо } < {, либо ] < [. Мы знаем, что этого не произойдет.Кроме того, некоторые строки подразумевают совершенно противоречивые вещи, такие как } < { AND { < }, которые, как мы знаем, невозможны. Устранение всех этих строк дает всего 6 строк:

# [ < { [ < } ] < { ] < } Collision? Example 
1  T  T  T  T   F  [ ] { } 
3  T  T  F  T   T  [ { ] } 
4  T  T  F  F   T  [ { } ] 
11  F  T  F  T   T  { [ ] } 
12  F  T  F  F   T  { [ } ] 
16  F  F  F  F   F  { } [ ] 

Здесь мы можем видеть, что только две средние положения определяют, есть ли столкновение. А именно, ([ < }) AND NOT (] < {). Это эквивалентно ([ < }) AND (] >= {) (отрицание второго компаратора), что эквивалентно SQL WHERE ('from' < $TO AND 'to' >= $FROM). Это семантически эквивалентно положению Павла (запрет на работу через <= до конца).

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