如何正确处理查询约束中的日期
Posted
技术标签:
【中文标题】如何正确处理查询约束中的日期【英文标题】:How to correctly handle dates in queries constraints 【发布时间】:2011-02-02 16:05:56 【问题描述】:我目前正在使用以下查询在 2010 年 6 月完成所有检查:
select inspections.name
from inspections
where
to_char(inspections.insp_date, 'YYYY') = 2010 and
to_char(inspections.insp_date, 'MM') = 06;
但这感觉有点尴尬。难道没有更好的方法来做到这一点吗?看着http://infolab.stanford.edu/~ullman/fcdb/oracle/or-time.html 似乎并非如此。我正在使用 Oracle,如果它有所作为的话。
谢谢
【问题讨论】:
【参考方案1】:我喜欢尽可能使用范围比较,因为这可以被优化器用于索引扫描:
select inspections.name
from inspections
where inspections.date >= DATE '2010-06-01'
and inspections.date < DATE '2010-07-01'
【讨论】:
hmmmm,反过来,我认为它比原始查询不太清楚:( @devoured elysium :我猜这是主观的,而使用索引的能力不是:) 我认为更清楚的是,当有一个非常好的方法会使用索引时,原始的 qery 和编写的 SQL 永远不会使用索引,这是一个糟糕的主意。任何编写 SQL 的人都需要了解什么是 sargable,什么不是。清晰度(这是程序员的主观判断)不会胜过数据库查询的性能。【参考方案2】:我同意文森特的回答,但为了完整起见,您可以简化为:
select inspections.name
from inspections
where
to_char(inspections.insp_date, 'YYYYMM') = '201006';
这甚至可以使用索引,只要索引是:
create index x on inspections (to_char(insp_date, 'YYYYMM'));
【讨论】:
很难理解 201006 发生了什么 :( @devoured:真的吗?好吧,您可以改用“YYYY-MM”和“2010-06”。 杰弗里你没有认真对待这个!【参考方案3】:select inspections.name
from inspections
where
extract(year from inspections.insp_date) = 2010 and
extract(month from inspections.insp_date) = 6;
【讨论】:
看起来不错。但它似乎是某种子查询。有效率吗?谢谢! 没有子查询,只有用于简单函数的 oracle 特定语法。 EXTRACT() 并不特定于 Oracle;这是标准 SQL。【参考方案4】:另一种选择是
SELECT inspections.name
FROM inspections
WHERE TRUNC( inspections.insp_date, 'MM' ) = date '2010-06-01';
从效率的角度来看
Vincent 的解决方案可能会在 INSP_DATE 对索引使用范围扫描(假设该表有许多个月的数据,因此索引访问将是最有效的计划)。 假设表有很多个月的数据,我的查询可能会再次在 TRUNC(insp_date, 'MM') 上使用基于函数的索引。如果不同月份的行数有很大差异,则优化器的基数估计在这个基于函数的索引上可能比在直接 INSP_DATE 索引上更准确,但这在查询中不太重要这个简单。但是,如果您开始将此查询嵌套在其他地方,它可能会发挥作用。但是,如果您出于其他原因需要索引 INSP_DATE,则维护两个不同的索引可能会浪费时间和空间。 您的初始查询和 Lev 的查询都可能使用基于复合函数的索引(尽管您希望包含显式 TO_NUMBER 或与字符串而不是数字进行比较以避免隐式转换)。但是,复合索引可能是维护效率最低的(尽管我们在这里讨论的是相对较小的差异),并且在我看来是最不干净的索引替代品。【讨论】:
如果没有完整的典型查询列表,很难预测索引效率。以上是关于如何正确处理查询约束中的日期的主要内容,如果未能解决你的问题,请参考以下文章