查找两个日期之间的日期(最佳实践)
Posted
技术标签:
【中文标题】查找两个日期之间的日期(最佳实践)【英文标题】:Finding dates between two dates (Best practice) 【发布时间】:2014-09-01 12:16:31 【问题描述】:我有 2 个 SQL 脚本。像这样的:
"Date" > '2014-04-11' AND "Date" <= '2014-04-12'
另一个是这样的:
"Date" BETWEEN '2014-04-11' AND '2014-04-12'
现在我想知道是否有任何特定的最佳实践,一个做一个优于另一个的原因,如果由于某些明显的原因,其中一个更好,我错过了某个地方。
【问题讨论】:
这两个查询不是同义词。BETWEEN
包含两个参数。我建议阅读这两篇文章; What do BETWEEN and the devil have in common? 和 Bad habits to kick : mis-handling date / range queries。尽管是为 SQL Server 编写的,但许多参数对 Oracle 仍然有效。
不是相当的同义词;第一个有>
而不是>=
,这可能是问题中的错误。不过,您想要找到哪些数据并不完全清楚。 (我还建议您不要使用带引号的标识符或隐式日期转换,但两者都超出了问题的范围)。
感谢您提供的链接,我一直在寻找这个主题,但我的“GoogleFu”在这件事上没有找到任何东西。
【参考方案1】:
您正在寻求最佳实践。我认为以下是最佳做法:
"Date" >= DATE '2014-04-11' AND "Date" < DATE '2014-04-12' + 1
首先,注意DATE
关键字的使用。您的问题是关于 dates 的,但您使用的是 Oracle 不直接支持的日期格式。令人高兴的是,Oracle 支持具有 ISO 标准格式的 ANSI 标准 DATE
关键字。
其次,我添加了一个+1
,以便您可以看到时间段的结束,这大概就是您希望在代码中看到的内容。它不应该影响性能,因为+ 1
是一个常数。
第三,一个日期常数有一个时间分量。如果未指定,则为日期的午夜。所以,表达式:
"Date" BETWEEN '2014-04-11' AND '2014-04-12'
真的是:
"Date" >= TIMESTAMP '2014-04-11 00:00:00' AND "Date" <= TIMESTAMP '2014-04-12 00:00:00'
也就是说,恰好包括较晚日期的一个时间,即午夜的第一个瞬间。这通常不是您想要的。 Oracle 在两个方面使这个问题变得更糟:
date
数据类型包含时间组件。
呈现date
值的默认方式没有时间组件。
所以,为了安全起见,请使用以下规则:
不要在约会时使用between
。
第一次约会时使用>=
。
第二个用户<
。
Aaron Bertrand 有一个 blog 正是关于这个主题的。虽然它专门针对 SQL Server,但其中许多想法适用于 Oracle ——尤其是因为 Oracle 中的 date
数据类型包括时间。
【讨论】:
"Date" 是抽象的,但由于原始列名在这种情况下没有意义,我冒昧地将其更改为更易读的名称,尽管不是那么正确。【参考方案2】:SQL> create table date_tab as select sysdate + level d from dual connect by rownum < 10;
Table created.
在之间使用:
SQL> set autotrace traceonly
SQL> select * from date_tab where d between sysdate + 1 and sysdate + 3;
Execution Plan
----------------------------------------------------------
Plan hash value: 290508398
...
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SYSDATE@!+1<=SYSDATE@!+3)
2 - filter("D">=SYSDATE@!+1 AND "D"<=SYSDATE@!+3)
使用日期间隔:
SQL> select * from date_tab where d > sysdate + 1 and d <= sysdate + 3;
Execution Plan
----------------------------------------------------------
Plan hash value: 290508398
...
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SYSDATE@!+1<SYSDATE@!+3)
2 - filter("D">SYSDATE@!+1 AND "D"<=SYSDATE@!+3)
如您所见,oracle 优化器将between
谓词重写为"D">=SYSDATE@!+1 AND "D"<=SYSDATE@!+3
因此,如果您使用第二个变体,oracle 执行的操作比第一个变体少一步。
【讨论】:
以上是关于查找两个日期之间的日期(最佳实践)的主要内容,如果未能解决你的问题,请参考以下文章