我已经用这样的SQL语句创建了PreparedStatement
:
SELECT *
FROM MY_TABLE
WHERE MY_DATE = ?
我使用
设置MY_DATE
值
preparedStatement.setTimestamp(1, myDate);
这样,数据库会检查整个时间戳是否相等。
现在我想将just的粒度减少到几分钟。我怎样才能做到这一点?
答案 0 :(得分:1)
如果使用TRUNC()函数,则可以忽略该值的粒度,低于某个级别。
所以,在你的情况下:
SELECT *
FROM MY_TABLE
WHERE TRUNC(MY_DATE, 'MI') = TRUNC(?, 'MI')
其他粒度可用:有关详细信息,请参阅Oracle's Documentation(默认情况下,截断到相关日期的00:00:00)。
当然,如果您存储的时间戳已被截断为分钟,那么您可以省略TRUNC的左手调用,并利用索引(如果该列上有一个索引)。
答案 1 :(得分:1)
使用 TRUNC 会抑制日期列上的任何常规索引。提高性能的一种方法是创建基于功能的索引。
但是,更好的方法是使用显式范围条件。
例如,
SELECT *
FROM MY_TABLE
WHERE
MY_DATE >= TO_DATE('24-MAR-2015','DD-MON-YYYY')
AND MY_DATE < TO_DATE('24-MAR-2015','DD-MON-YYYY')+1;
或者,
使用 BETWEEN (无论如何,优化程序会将其重写为上述范围条件):
SELECT *
FROM MY_TABLE
WHERE
MY_DATE BETWEEN TO_DATE('24-MAR-2015','DD-MON-YYYY')
AND TO_DATE('24-MAR-2015','DD-MON-YYYY') + (1-1/24/60/60);
更多信息
使用范围条件,优化器实际上以下列方式重写查询:
access("MY_DATE">=TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"MY_DATE"<TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
并且会有INDEX RANGE SCAN
次操作而不是TABLE ACCESS FULL
。如果使用 TRUNC ,没有基于函数的索引,这就是优化器应用过滤谓词的方式:
filter(TRUNC(INTERNAL_FUNCTION("MY_DATE"))=TO_DATE(' 2015-03-24 00:00:00',
'syyyy-mm-dd hh24:mi:ss'))
的文章