半开放(或半开放,半封闭,半有界)间隔([a,b)
,其中x
属于间隔iff a <= x < b
)在编程中非常常见,因为它们具有许多方便的属性。
谁能提供解释SQL为什么BETWEEN
使用封闭间隔([a,b]
)的理由?这是特别的。日期不便。你怎么会BETWEEN
这样
半开放(或半开放,半封闭,半有界)间隔([a,b)
,其中x
属于间隔iff a <= x < b
)在编程中非常常见,因为它们具有许多方便的属性。
谁能提供解释SQL为什么BETWEEN
使用封闭间隔([a,b]
)的理由?这是特别的。日期不便。你怎么会BETWEEN
这样
Answers:
我认为包容性BETWEEN
比半开放时间间隔更直观(并且显然SQL设计者也是如此)。例如,如果我说“选择一个介于1到10之间的数字”,大多数人将包括数字1和10。对于非开发人员来说,开放式间隔实际上特别令人困惑,因为它是不对称的。SQL是偶尔使用非程序员进行简单的查询和半开放式的语义本来多为他们多混乱。
问题:为什么SQL的BETWEEN具有包容性?
解答:由于SQL语言设计者做出的设计决策很差,因此他们未能提供语法,使开发人员无法指定BETWEEN的4个变体中的哪个(封闭式,半开放式,半开放式或开放式)。 ),他们更喜欢。
建议:除非/直到对SQL标准进行修订,否则不要在日期/时间中使用BETWEEN。而是养成将DATE范围比较编码为BETWEEN范围的开始和结束边界上的独立条件的习惯。这有点冗长,但是会使您编写直观的条件(因此不太可能出现错误)并且对于数据库优化器来说是清楚的,从而可以确定最佳的执行计划并使用索引。
例如,如果您的查询接受输入日期规范,并且应返回该日期的所有记录,则您可以将代码编码为:
WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1
尝试使用BETWEEN编写逻辑可能会导致性能问题和/或错误代码。三种常见的失误:
1) WHERE DATE_FIELD BETWEEN :dt AND :dt+1
几乎可以肯定这是一个错误-用户希望只看到特定日期的记录,但是最后一天将生成包含第二天凌晨12:00的记录的报告。
2) WHERE TRUNC(DATE_FIELD) = :dt
给出正确答案,但是将函数应用于DATE_FIELD将使大多数索引/统计信息无用(尽管有时DBA会尝试通过在日期字段中添加基于函数的索引来提供帮助-仍然会消耗大量的工作时间和磁盘空间,并增加IUD的开销桌上的操作)
3) WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60
Oracle高级专家Tom Kyte推荐了这种不太雅致(IMO)的解决方案。直到您整日在查询中发现结果不完整的“ 1-1 / 24/06/60”为止,或者直到您在TIMESTAMP字段上不小心使用了它,效果都很好。另外,它有点专有;与Oracle的DATE数据类型(可追溯到第二种)兼容,但需要调整为不同数据库产品的DATE / TIME精度。
解决方案:请ANSI SQL委员会通过修改BETWEEN语法来支持CLOSED / INCLUSIVE缺省选项的替代规范,以增强SQL语言规范。这样的事情可以解决问题:
表达式1 BETWEEN 表达式2 [ INCL [USIVE] | EXCL [USIVE]]和expr3 [ INCL [USIVE] | EXCL [USIVE]]
考虑表达WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(或仅仅是WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)变得多么容易
也许是ANSI SQL:2015?
exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3
,您可以保留between运算符,因此您知道它是一个范围谓词,并且不等式谓词可确保它是半开放的。
包含(a <= x <= b
)和排斥(a < x < b
)两者几乎相同,因此在制定标准时,他们只需选择一个即可。普通英语中的“之间”通常是包含性的,并且SQL语句的读法类似于英语句子,因此包含性是明智的选择。
a <= x < b
是半开。
运算符没有被调用∩[a,b)
,它被称为BETWEEN
,所以它的语义要比英语谓词“处于半开区间”的语义更适合英语单词 “在...之间”。
BETWEEN
操作员不使用英语短语“在...之间”的语义。在英语中,“之间”是将事物分隔开的时间,空间或间隔(即,它是排他的)。如果您尝试踢球,则球必须在杆之间移动才能得分。如果您发帖失败,则无法在两者之间传递-没有分数。