我正在使用oracle数据库。我想执行一个查询来检查两个日期之间的数据。
NAME START_DATE
------------- -------------
Small Widget 15-JAN-10 04.25.32.000000 PM
Product 1 17-JAN-10 04.31.32.000000 PM
select * from <TABLENAME> where start_date
BETWEEN '15-JAN-10' AND '17-JAN-10'
但我从上面的查询中得不到任何结果。我想我必须使用“喜欢”和“%”。但我不知道在哪里使用它们。请点亮这个。
提前感谢。
答案 0 :(得分:80)
从您的输出判断,您似乎已将START_DATE定义为时间戳。如果是常规日期,Oracle将能够处理隐式转换。但是因为它不是你需要明确地将这些字符串转换为日期。
SQL> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss'
2 /
Session altered.
SQL>
SQL> select * from t23
2 where start_date between '15-JAN-10' and '17-JAN-10'
3 /
no rows selected
SQL> select * from t23
2 where start_date between to_date('15-JAN-10') and to_date('17-JAN-10')
3 /
WIDGET START_DATE
------------------------------ ----------------------
Small Widget 15-JAN-10 04.25.32.000
SQL>
但我们仍然只得到一排。这是因为START_DATE有一个时间元素。如果我们没有指定时间组件Oracle将其默认为午夜。这对于BETWEEN
的来说是好的,但到之前不适用于
SQL> select * from t23
2 where start_date between to_date('15-JAN-10')
3 and to_date('17-JAN-10 23:59:59')
4 /
WIDGET START_DATE
------------------------------ ----------------------
Small Widget 15-JAN-10 04.25.32.000
Product 1 17-JAN-10 04.31.32.000
SQL>
修改强>
如果您无法传递时间组件,则有几个选择。一种是更改WHERE子句以从条件中删除时间元素:
where trunc(start_date) between to_date('15-JAN-10')
and to_date('17-JAN-10')
这可能会对性能产生影响,因为它会在START_DATE取消任何b-tree索引的资格。您需要构建基于函数的索引。
或者,您可以将时间元素添加到代码中的日期:
where start_date between to_date('15-JAN-10')
and to_date('17-JAN-10') + (86399/86400)
由于存在这些问题,许多人更愿意通过检查日期边界来避免使用between
:
where start_date >= to_date('15-JAN-10')
and start_date < to_date('18-JAN-10')
答案 1 :(得分:22)
你需要将它们转换为实际日期而不是字符串,试试这个:
SELECT *
FROM <TABLENAME>
WHERE start_date BETWEEN TO_DATE('2010-01-15','YYYY-MM-DD') AND TO_DATE('2010-01-17', 'YYYY-MM-DD');
编辑处理指定的格式:
SELECT *
FROM <TABLENAME>
WHERE start_date BETWEEN TO_DATE('15-JAN-10','DD-MON-YY') AND TO_DATE('17-JAN-10','DD-MON-YY');
答案 2 :(得分:3)
正如APC正确指出的那样,你的start_date列似乎是一个TIMESTAMP,但它也可以是TIMESTAMP WITH LOCAL TIMEZONE或TIMESTAMP WITH TIMEZONE数据类型。如果您的数据库服务器与您自己处于不同的时区,这些可能会影响您对数据执行的任何查询。但是,让我们保持这一点,并假设您与服务器位于同一时区。首先,为了给您信心,请检查start_date是否为TIMESTAMP数据类型。
使用SQLPlus DESCRIBE命令(或IDE中的等效命令)验证此列是TIMESTAMP数据类型。
例如
DESCRIBE mytable
应该报告:
Name Null? Type
----------- ----- ------------
NAME VARHAR2(20)
START_DATE TIMESTAMP
如果报告为Type = TIMESTAMP,那么您可以使用最简单的TO_TIMESTAMP日期转换查询日期范围,不需要参数(或图片)。
我们使用TO_TIMESTAMP来确保优化器考虑START_DATE列上的任何索引。 APC的回答还指出,可能已在此列上创建了基于函数的索引,这将影响SQL谓词,但我们无法在此查询中对此进行评论。如果您想知道如何找出已应用于表格的索引,请发布另一个问题,我们可以单独回答。
因此,假设start_date上有一个索引,这是一个TIMESTAMP数据类型,并且您希望优化器考虑它,那么您的SQL将是:
select * from mytable where start_date between to_timestamp('15-JAN-10') AND to_timestamp('17-JAN-10')+.9999999
+ .99999999非常接近但不是1,所以17-JAN-10的转换将尽可能接近当天的午夜,因此您查询返回两行。
数据库将显示BETWEEN从 15-JAN-10 00:00:00:0000000 到 17-JAN-10 23:59:59:99999 因此将包括2010年1月15日,16日和17日的所有日期,无论时间戳的时间成分如何。
希望有所帮助。
Dazzer
答案 3 :(得分:1)
查询之间的日期
SELECT *
FROM emp
WHERE HIREDATE between to_date (to_char(sysdate, 'yyyy') ||'/09/01', 'yyyy/mm/dd')
AND to_date (to_char(sysdate, 'yyyy') + 1|| '/08/31', 'yyyy/mm/dd');
答案 4 :(得分:1)
也可以使用以下查询:
select *
from t23
where trunc(start_date) between trunc(to_date('01/15/2010','mm/dd/yyyy')) and trunc(to_date('01/17/2010','mm/dd/yyyy'))