2010-08-04 91 views
1

我需要查找一些在四分之一范围内创建的记录。例如,我在寻找2008年第四季度和2010年第一季度之间创建的所有记录,我有这个在我的WHERE子句:使用四分之一格式的Oracle to_date函数

...and r.record_create_date between to_date('2008 4','YYYY Q') 
           and to_date('2010 1','YYYY Q') 

但甲骨文说:ORA-01820: format code cannot appear in date input formatQ是有效的日期格式符号,所以我不确定发生了什么。这甚至是在日历季度之间找到价值的有效方法,还是有更好的方法?


也很有趣,可能相关的,如果我执行此:

select to_date('2009','YYYY') from dual; 

在我的IDE显示的值2009-08-01。我本来预计2009-08-04,因为今天2010-08-04

此:

select to_date('2009 1','YYYY Q') from dual; 

当然,失败。

(Oracle 10g中)

回答

3

Oracle说打字困难得多: ORA-01820: format code cannot appear in date input formatQ是有效的日期格式符号,所以我不确定发生了什么。

请参阅表2.15的第二列http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements004.htm#i34948。当转换为日期,时间戳等时,不允许所有格式元素。

我建议不要在日期范围检查之间使用。人们通常会在期望被包括的结束日期内错过价值。所以我会翻译:

and r.record_create_date between to_date('2008 4','YYYY Q') 
          and to_date('2010 1','YYYY Q') 

and to_date('2008-10-01', 'YYYY-MM-DD') <= r.record_create_date 
and record_create_date < to_date('2010-04-01', 'YYYY-MM-DD') -- < beginning of 2Q2010. 
1

有人问OTN上的同一个问题:http://forums.oracle.com/forums/thread.jspa?threadID=1081398&tstart=255

问题的关键是,你可以在TO_DATE函数指定 “Q”。

鉴于您已指定日期的一部分,为什么不提供日期为整个?请注意,to_date('2010 1','YYYY Q')会给你2010年1月1日,当你真的想2010年3月31日...在一秒钟到午夜。

+1

当你真的想2010年3月31日* 11:59:59 * – 2010-08-04 18:55:25

+0

@Shannon遣散:所有的人,愿者上钩...... :) – 2010-08-04 19:05:55

0

我认为最好的方法就是输入季度开始日期和季度结束日期,而不用担心to_date。我认为,如果你使用

between '1-Jan-10' and '31-Dec-10' 

例如,那你就不要(在Oracle我相信)需要TO_DATE,它是不是比季度数

+0

嗯,我的最终代码我有计划循环通过季度数字1到4,但我想我可以有一个数组索引1到4与适当的价值为季度的实际开始和结束日期(或类似的东西)。 – FrustratedWithFormsDesigner 2010-08-04 18:59:16

1

由于到几个月宿舍之间的关系是一个对很多人来说,没有任何意义做TO_DATE(“2008年1”,' yyyy q');什么日期应该返回?本季度第一季度,本季度末... ...? (另一方面,将日期转换为四分之一 - 如TO_CHAR(SYSDATE,'yyyy q')是有意义的,因为特定日期只存在于四分之一。)

因此,如果您确实想要一个查询对于两个季度之间的日期,您将不得不“自行”(明确说明季度开始/结束的日期)请不要使用像WHERE date_value BETWEEN'date string1'和'date string2'之类的东西,而不使用TO_DATE函数。它假定默认的日期格式,并且在某些情况下可以完全避免可能有用的索引。

下面是一个例子,其中相同的查询可以有不同的结果。

select sysdate from dual where sysdate between '1-Jan-10' and '31-Dec-10'; 


SYSDATE 
--------- 
04-AUG-10 

SQL> alter session set nls_date_format = 'YYYY-MM-DD'; 

Session altered. 

SQL> select * from dual where sysdate between '1-Jan-10' and '31-Dec-10'; 

no rows selected 

(请注意,在二审不会返回错误。这只是假定1月10日,0001日和12月10日,0031.)

+0

我不同意这个逻辑。月份和日期之间的关系也是一对多的,'YYYY-MM'是有效的。 – 2016-01-19 13:55:18

0

要甲骨文计算季度和第一天从年和季度季度最后一天: 我用事实

START_MONTH = -2 + 3 *季度

LAST_MONTH = 3 *季度

variable v_year number 

variable v_quarter number 

exec :v_year  :=2017 

exec :v_quarter:=4 

select :v_year as year, 
     :v_quarter as quarter, 
     to_date(:v_year||to_char(-2+3*:v_quarter,'fm00'),'yyyymm')  as quarter_start, 
     last_day(to_date(:v_year||to_char(3*:v_quarter,'fm00')||'01 23:59:59','yyyymmdd hh24:mi:ss')) as quarter_end 
from dual a; 


YEAR|QUARTER|QUARTER_START  |QUARTER_END   
2017|  4|2017-10-01 00:00:00|2017-12-31 23:59:59