2010-04-10 63 views
4

我有一个包含约49403459记录的表。如何优化在日期的where子句中具有to_char的Oracle查询

我想查询日期范围内的表格。说04/10/201004/10/2010。但是,日期以格式10-APR-10 10.15.06.000000 AM(时间戳)存储在表中。

,当我做

SELECT bunch,of,stuff,create_date 
FROM myTable 
WHERE TO_CHAR (create_date,'MM/DD/YYYY)' >= '04/10/2010' 
AND TO_CHAR (create_date, 'MM/DD/YYYY' <= '04/10/2010' 

我得到529行,但在255.59秒的成绩!这是因为我想我正在做每个记录上的TO_CHAR。

然而,当我做

SELECT bunch,of,stuff,create_date 
FROM myTable 
WHERE create_date >= to_date('04/10/2010','MM/DD/YYYY') 
AND create_date <= to_date('04/10/2010','MM/DD/YYYY') 

然后我得到0结果0.14秒。

如何快速查询此查询并仍然有效(529)结果?

在这一点上我不能改变索引。现在我认为索引创建在create_date列。

如何将两个日期范围转换为第一个日期范围转换为全部为0的时间戳,并将第二个日期范围转换为日期的最后时间戳时间戳。如果这是有道理的...?

where子句取没有结果以下两种:

WHERE    
create_date >= to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 
AND 
create_date <= to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 

回答

2

在第一个查询,你正在做一个字符比较,而不是一个日期比较,这不应该产生正确的结果。

例如,使用你的逻辑,01/02/2009将大于01/01/2010因为天组件“02”是比天还组件“01”比较时,人物和年度将永远不会被评价更高。

+0

谢谢。我尝试过,但仍然没有得到任何结果。请参阅我的编辑 – Josh 2010-04-10 18:41:50

+0

我编辑了我的答案。我认为你的第二个查询可能是正确的。第一个查询给你不正确的结果。 – newdayrising 2010-04-10 18:43:44

+0

不......我可以查询表格并查看是否有今天创建的记录。 .. – Josh 2010-04-10 18:46:19

2

这工作:

WHERE    
create_date >= to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 
AND 
create_date <= to_timestamp('04/10/2010 23:59:59:123000','MM/DD/YYYY HH24:MI:SS.FF') 
1
SELECT bunch,of,stuff,create_date 
    FROM myTable 
WHERE create_date >= to_date('04/10/2010','MM/DD/YYYY') 
    AND create_date < to_date('04/11/2010','MM/DD/YYYY') 

日期04/10/2010包括从半夜10日的所有日期的值,直到下午11:59:59,所以让一切小于11将覆盖所有的基地。另一种方法是确保myTable中的数据在数据输入时截断了CREATE_DATE字段;我更喜欢为DATE字段做这件事,如果我关心时间组件,我使用TIMESTAMPs。

3

当然,这并不工作:

WHERE    
    create_date >= to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 
AND 
    create_date <= to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 

因为这只会返回行,其中CREATE_DATE是2010年4月10日12:00 AM 正是

如果你想获得其中CREATE_DATE发生的任何时间对2010年4月10日当天的所有行,使用:

WHERE    
    create_date >= to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 
AND 
    create_date < to_timestamp('04/11/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 

或者如果你喜欢:

WHERE create_date BETWEEN to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 
         AND to_timestamp('04/10/2010 23:59:59.999999','MM/DD/YYYY HH24:MI:SS.FF') 

由方式,当你想要表示午夜时,你可以把所有其他部分留下。所以,你可以只说:

WHERE    
    create_date >= to_timestamp('04/10/2010','MM/DD/YYYY') 
AND 
    create_date < to_timestamp('04/11/2010','MM/DD/YYYY') 
4

我得到529行,但在255.59秒! 这是因为我想我正在做每个记录上的TO_CHAR 。

如果你要generate an execution plan你的第一个查询...

explain plan for 
SELECT bunch,of,stuff,create_date 
FROM myTable 
WHERE TO_CHAR (create_date,'MM/DD/YYYY)' >= '04/10/2010' 
AND TO_CHAR (create_date, 'MM/DD/YYYY') <= '04/10/2010' 
/

...你会看到它做了全表扫描。这是因为to_char()阻止在CREATE DATE上使用您的索引。

你不说花费了多少时间,当你跑到返回结果...

SELECT bunch,of,stuff,create_date 
FROM myTable 
WHERE    
create_date >= to_timestamp('04/10/2010 00:00:00.000000','MM/DD/YYYY HH24:MI:SS.FF') 
AND 
create_date <= to_timestamp('04/10/2010 23:59:59:123000','MM/DD/YYYY HH24:MI:SS.FF') 
/

...但我希望它是方式4分钟内接近0.14秒。

0

您的第一个查询正在进行字符串比较,结果错误。 你的第二查询需要是:

WHERE CREATE_DATE> = TRUNC(TO_DATE('04/10/2010' , 'MM/DD/YYYY'))

或添加HH :mi:ss给谓词。这不是简单的工作,因为你用不同的方式格式化日期以达到Oracle的期望。