我有以下查询:
select * from sa_tran_head WHERE
((TRAN_DATETIME) BETWEEN NVL(:STARTDATE, TRAN_DATETIME) AND NVL(:ENDDATE, TRAN_DATETIME));
如果我放STARTDATE = 21-JUN-2016 and ENDDATE = 21-JUN-2016
,它就不会显示任何内容。
当我放STARTDATE = 21-JUN-2016 and ENDDATE = 22-JUN-2016
时,它会显示21-JUN-2016的结果。
为什么会这样?
答案 0 :(得分:1)
我的猜测? value
还存储时间价值?
使用TRAN_DATETIME
:
TRUNC()
答案 1 :(得分:0)
日期时间在内部被视为正确的时间戳。当您将日期提及为21-Jun-2016
时,会将其视为21-Jun-2016 00:00:00.000
。因此,它会在第一个条件中检查21-Jun-2016 00:00:00.000
和21-Jun-2016 00:00:00.000
中的值,并解释您获得的输出。
答案 2 :(得分:0)
可能会忽略小时,分钟和秒钟? 看一下例子:
create table t(v date)
/
insert into t(v) values(to_date('2016-06-23 23:00:00', 'yyyy-mm-dd hh24:mi:ss'))
/
-- no rows
select * from t where
v BETWEEN Nvl(to_date('2016-06-23 08:00:00', 'yyyy-mm-dd hh24:mi:ss'), v)
AND NVL(to_date('2016-06-23 08:00:00', 'yyyy-mm-dd hh24:mi:ss'), v);
/
-- exactly one
select * from t where
v BETWEEN Nvl(to_date('2016-06-23 08:00:00', 'yyyy-mm-dd hh24:mi:ss'), v)
AND NVL(to_date('2016-06-24 08:00:00', 'yyyy-mm-dd hh24:mi:ss'), v);
/
答案 3 :(得分:0)
Oracle将日期存储在7- or 8-byte data structure中,始终包含时间组件。
当您有一个日期TO_DATE( '21-JUN-2016', 'DD-MON-YYYY' )
时,Oracle会创建时间为00:00:00
的日期。
如果你这样做:
WHERE TRAN_DATETIME BETWEEN TO_DATE( '21-JUN-2016 00:00:00', 'DD-MON-YYYY HH24:MI:SS' )
AND TO_DATE( '21-JUN-2016 00:00:00', 'DD-MON-YYYY HH24:MI:SS' )
然后,您只会获得当天所需的结果且具有时间成分00:00:00
。
现在,您可以使用TRUNC()
将时间组件设置为00:00:00
:
WHERE TRUNC( TRAN_DATETIME ) BETWEEN DATE '2016-06-21' AND DATE '2016-06-21'
但是,如果TRAN_DATETIME
列上有索引,则此查询将不会使用它(但是,它可以在TRUNC( TRAN_DATETIME )
上使用基于函数的索引)。
可以使用索引的解决方案是:
WHERE TRAN_DATETIME >= :start_date
AND TRAN_DATE < :end_date + INTERVAL '1' DAY
(假设:start_date
和:end_date
是使用00:00:00
的时间成分传入的绑定变量 - 这就是你似乎正在做的事情。)
合并NVL
语句:
WHERE ( :start_date IS NULL OR TRAN_DATETIME >= :start_date )
AND ( :end_date IS NULL OR TRAN_DATE < :end_date + INTERVAL '1' DAY )