如何正确处理查询约束中的日期

时间:2011-02-02 16:05:57

标签: sql database oracle constraints

我目前正在使用以下查询来完成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,如果它有所作为。

由于

4 个答案:

答案 0 :(得分:11)

我喜欢在可能的情况下使用范围比较,因为优化器可以将其用于索引扫描:

select inspections.name
  from inspections
 where inspections.date >= DATE '2010-06-01'
   and inspections.date < DATE '2010-07-01'

答案 1 :(得分:4)

我同意文森特的回答,但为了完整起见,你可以将你简化为:

select inspections.name
from inspections
where
  to_char(inspections.insp_date, 'YYYYMM') = '201006';

如果索引是:

,那甚至可以使用索引
create index x on inspections (to_char(insp_date, 'YYYYMM'));

答案 2 :(得分:3)

select inspections.name
from inspections
where
  extract(year from inspections.insp_date) = 2010 and
  extract(month from inspections.insp_date) = 6;

答案 3 :(得分:3)

另一种选择是

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或与字符串而不是数字进行比较以避免隐式转换)。不过,综合指数可能维持效率最低(虽然我们在这里谈论的是相对较小的差异),并且认为我是最不干净的指数替代品。