【问题标题】:Check time interval using SQL condition使用 SQL 条件检查时间间隔
【发布时间】:2011-03-12 11:08:39
【问题描述】:

我在 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.:我需要找到冲突以提醒用户这个新时期已经存在或与现有时期发生冲突。

【问题讨论】:

  • 您使用什么表示周期,例如封闭开放?换句话说,你会认为(from 1 to 5)(from 5 to 6) 发生冲突吗?

标签: sql logic conditional-statements intervals


【解决方案1】:

我遇到了这个问题,只是想尝试展示真值表如何识别 Paul 已经发布的简化逻辑。

假设您有一个区间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 ( [ &lt; { AND [ &lt; } AND ] &lt; { AND ] &lt; } ) AND NOT ( [ &gt;= { AND [ &gt;= } AND ] &gt;= { AND ] &gt;= } )

但是我们知道,由于 { &lt; }[ &lt; ],这简化为

NOT ( [ &lt; { AND ] &lt; { ) AND NOT ( [ &gt;= } AND ] &gt;= } )

对应的SQL:

WHERE NOT ('from' &lt; $FROM and 'to' &lt; $FROM ) AND NOT ('from' &gt; $TO and 'to' &gt; $TO)(类似于@TiuTalk 的建议)。

但是,我们已经假设 { &lt; }[ &lt; ]。这很关键。查看真值表中标记为* 的行。在这些行中,} &lt; {] &lt; [。我们知道那些不会发生。另外,有些行暗示了完全矛盾的事情,比如} &lt; { AND { &lt; },我们知道这是不可能的。消除所有这些行只得到 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       { } [ ]

在这里,我们可以看到只有中间的两个子句确定是否存在冲突。即( [ &lt; } ) AND NOT ( ] &lt; { )。这相当于( [ &lt; } ) AND ( ] &gt;= { )(否定第二个比较器),相当于SQL WHERE ('from' &lt; $TO AND 'to' &gt;= $FROM)。这在语义上等同于 Paul 的条款(除非通过 &lt;= 一直工作到最后)。

【讨论】:

    【解决方案2】:
    WHERE ($TO >= `from` AND $FROM <= `to`)
    

    请注意,这适用于新范围与整个范围重叠、仅部分重叠以及包含它的情况。

    【讨论】:

    • 我曾在 80 年代从事 GIS 系统工作。交叉和重叠是我的第二天性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-21
    • 2012-05-25
    • 1970-01-01
    • 2021-03-02
    • 2020-02-14
    • 1970-01-01
    相关资源
    最近更新 更多