我在SQL中存储了一些间隔,例如:
id INT
from DATE
to DATE
如果NEW间隔与现有间隔冲突,如何仅使用一个条件(如果可能)进行检查?
示例:
|-----------| (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。:我需要找到碰撞来提醒用户这个新时期已经存在或与现有时期发生冲突。
答案 0 :(得分: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)
。这在语义上等同于保罗的条款(除非通过<=
工作到最后)。
答案 1 :(得分:2)
WHERE ($TO >= `from` AND $FROM <= `to`)
注意这适用于新范围与整个范围重叠的情况,当它只是部分重叠时以及它也包含它时。