Oracle 中的日期范围问题。如何正确获取这种格式的日期范围?

Date range problems in Oracle. How do I correctly grab date ranges in this format?

我有这个 Oracle 数据库,它有一个格式如下的日期列表:mm/dd/yy 0:00:00 AM/PM(1 代表一月,而不是 01;1 代表一天,而不是 01,等等)。

当我尝试查询时:

select DATELIST from CORE.DATE_TEST
where to_date(DATELIST) >= to_date('8/27/2015', 'mm/dd/yy') AND to_date(DATELIST, 'mm/dd/yy') <= to_date('9/27/2015', 'mm/dd/yy');

它给我以下错误:ORA-01843: not a valid month。我也看不出 27 是一个有效的月份,但如果我尝试

它会接受该输入

当我尝试将其更改为预期的日期格式时:

  1. m/dd/yy
  2. mm/dd/yyyy
  3. m/d/yy

我收到此错误:ORA-01821: date format not recognized

当我将它切换到 dd/mm/yy 时,它有点工作,但不是真的;它给了我无效的结果。

但是,这有效:

select DATELIST from CORE.DATE_TEST
where to_date(DATELIST) >= to_date('8/27/2015', 'mm/dd/yy') 

PL/SQL 脚本因以下添加而中断:

AND to_date(DATELIST, 'mm/dd/yy') <= to_date('9/27/2015', 'mm/dd/yy');

当我用这个替换上面的代码时:

SELECT to_date(DATELIST, 'dd/mm/yy') 
    FROM CORE.DATE_TEST
WHERE DATELIST >= to_date('8/27/2015', 'mm/dd/yy')
    AND DATELIST <= to_date('9/27/2015', 'mm/dd/yy');

它可以工作,而且速度快一百万倍,但它无法正确解析日期范围。小于或等于 (<=) 运算符仅抓取 8/27/20159/26/2015 之间的数据。不是应该从 8/27/2015 到 9/27/2015 吗?

所以我把最后一行改成这样:

AND DATELIST <= to_date('9/27/2015', 'mm/dd/yy') + 1

...它有效,但我似乎没有正确处理这个问题。

我做错了什么?另外,如果有更好、更有效的方法,我会洗耳恭听。

你的原始问题中有很多问题,我会尝试在这里解决其中的部分或全部问题:

When I try a query such as:
select DATELIST from CORE.DATE_TEST
where to_date(DATELIST) >= to_date('8/27/2015', 'mm/dd/yy') AND to_date(DATELIST, 'mm/dd/yy') <= to_date('9/27/2015', 'mm/dd/yy');
It gives me the following error: ORA-01843: not a valid month

您在指定 to_date(DATELIST) 时未指定日期格式,因此它将默认为默认日期格式的 NLS 设置。每当您使用 TO_DATE 以防止这种情况发生并确保您的日期格式明确时,您应该始终指定日期格式(并且您正在使用 yy 但您指定了 4 位数的年份,因此您应该使用yyyy).

试试这个(假设 DATELISTDATE 数据类型):

select TO_CHAR(DATELIST, 'DD-MON-YYYY HH24:MI:SS') -- Use whatever date format is clearest to you
  from CORE.DATE_TEST
 where DATELIST >= to_date('8/27/2015 00:00:00', 'mm/dd/yyyy hh24:mi:ss') AND DATELIST <= to_date('9/27/2015 23:59:59', 'mm/dd/yyyy hh24:mi:ss');

如果 DATELISTVARCHAR2,那么您需要查看值在列中存储的日期格式,并相应地格式化查询。

The lesser-than-or-equal-to (<=) operator is only grabbing data between 8/27/2015, and 9/26/2015. Isn't it supposed to get 8/27/2015 to 9/27/2015?

当您使用 TO_DATE 且未指定日期的时间部分时,它默认为 00:00:00 表示小时、分钟和秒。如果您想要完整的日期范围,请尝试更明确:

SELECT to_date(DATELIST, 'dd/mm/yy hh24:mi:ss') 
    FROM CORE.DATE_TEST
WHERE DATELIST >= to_date('8/27/2015 00:00:00', 'mm/dd/yyyy hh24:mi:ss')
    AND DATELIST <= to_date('9/27/2015 23:59:59', 'mm/dd/yyyy hh24:mi:ss');

查询速度快得多的原因是,我怀疑您在 DATELIST 列上有一个索引,当您用 TO_DATE 调用(例如 TO_DATE(DATELIST, 'mm/dd/yyyy').

如果 DATELIST 的数据类型是 DATE 则保留它,如果它是 VARCHAR2 那么您还有一些额外的日期格式问题。

希望对您有所帮助

编辑:

我认为您的问题与 DATE 数据类型 DATELIST 的隐藏时间部分有关。

如果你有以下价值: 2015 年 9 月 27 日 10:35:12

即使您不关心该日期的 10:35:12 部分,它仍然存在。如果您随后尝试使用以下 where 子句:

WHERE DATELIST >= TO_DATE('09/26/2015', 'MM/DD/RRRR')
  AND DATELIST <= TO_DATE('09/27/2015', 'MM/DD/RRRR');

那么该值将不会被拾取,因为它大于: 2015 年 9 月 27 日 00:00:00。

您需要将上限提高一天或指定时间部分,例如:

WHERE DATELIST >= TO_DATE('09/26/2015 00:00:00', 'MM/DD/RRRR HH24:MI:SS')
  AND DATELIST <= TO_DATE('09/27/2015 23:59:59', 'MM/DD/RRRR HH24:MI:SS');

编辑2: 与 OP 合作,他说这有效:

SELECT to_date(DATELIST, 'dd/mm/yy') as Date_Accessed 
  FROM CORE.DATE_TEST 
 WHERE (trunc(DATELIST) >= to_date('9/27/2015', 'mm/dd/yy')) 
   AND (trunc(DATELIST) <= to_date('9/30/2015', 'mm/dd/yy'));

虽然这会破坏 DATELIST 列上的任何索引。

不使用 to_date,而是使用 ANSI 日期文字:

DATE '2015-09-27'

来自 oracle 文档:

The ANSI date literal contains no time portion, and must be specified in exactly this format ('YYYY-MM-DD').