为什么我的日期字段的SQL查询有时需要trunc()(Oracle)?

时间:2010-10-07 22:08:25

标签: sql oracle datetime

我有两个表,我在每个表的日期列中查询。

在一种情况下,需要在日期字段上使用trunc()函数来获取值,而另一种情况则不需要。

这适用于表1:

SELECT to_char( datecol1 ,'mm/dd/yyyy hh:mm:ss') 
FROM table1 where datecol1    =to_date('10/07/2010', 'mm/dd/yyyy');

但是在表2中,上面的语法不起作用,我需要trunc(),例如:

SELECT to_char( datecol2 ,'mm/dd/yyyy hh:mm:ss') 
FROM table2 where trunc(datecol2) =to_date('10/07/2010', 'mm/dd/yyyy');

需要注意三点:

  1. 在使用to_char(datecol1,'mm / dd / yyyy hh:mm:ss')查询table1时,看起来好像所有时间都在12:00到12:10之间,但是全天都插入了值
  2. 将记录插入table1时我只插入mm / dd / yyyy,没时间
  3. 将记录插入table2时我插入了时间
  4. 有人可以解释一下:

    • 为什么table1上不需要截断但是在table2上?
    • 为什么table1中的所有值都在12:00到12:10之间?

2 个答案:

答案 0 :(得分:8)

在表1中,您没有数据的“时间”组件,因此日期应该匹配 - 这是您观察到的。但是,您使用mm格式化了部分时间 - 但mm ,而不是分钟(mi)。这就是为什么你看到12点以外的时间,以及为什么它们的范围只有12:10左右(你今年可能只有今年的数据?)

在table2中,由于您拥有数据的“时间”组件,因此需要将其截断以匹配仅日期值,这是to_date()函数返回的值,给定您使用的格式。

答案 1 :(得分:0)

*将记录插入table1时我只插入mm / dd / yyyy,没时间

将记录插入table2时,我插入了时间*

这就是为什么你需要第二个查询的截断。 to_date('10/07/2010', 'mm/dd/yyyy')正在生成一个时间组件为午夜的“日期”,就像没有时间组件的表1中的插入一样。在第二种情况下,有一个时间组件,trunc将其关闭,因此您只需比较日期部分to_date('10/07/2010', 'mm/dd/yyyy')的日期部分

如果dateCol1上有索引,您可能需要将第二个查询重写为:

SELECT to_char( datecol2 ,'mm/dd/yyyy hh:mi:ss')  
FROM table2 
WHERE to_date('10/07/2010', 'mm/dd/yyyy') <= dateCol2
and dateCol2 < to_date('10/08/2010', 'mm/dd/yyyy')

SELECT to_char( datecol2 ,'mm/dd/yyyy hh:mi:ss')  
FROM table2 
WHERE dateCol2 between to_date('10/07/2010', 'mm/dd/yyyy') 
    and to_date('10/07/2010 11:59:59 PM', 'MM/DD/YYYY HH12:Mi:SS AM')

或者在trunc(dateCol2)上创建基于函数的索引,而不是在dateCol2上创建普通索引,具体取决于其他查询。

因为参与函数的列通常不能使用索引,并且会强制执行表扫描,而是从优化器中取出选项。