我有一个包含约49403459
条记录的表格。
我想查询日期范围内的表格。说04/10/2010
到04/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')
答案 0 :(得分: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秒。
答案 1 :(得分: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为4/10/2010 12:00 AM 完全的行!
如果您希望在2010年4月10日的任何时间获取create_date所在的所有行,请使用:
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')
答案 2 :(得分:2)
在第一个查询中,您正在进行字符比较而不是日期比较,这不应该产生正确的结果。
例如,使用您的逻辑,01/02/2009
将大于01/01/2010
,因为当比较时,日组件“02
”大于日期组件“01
”字符和年份永远不会被评估。
答案 3 :(得分: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')
答案 4 :(得分: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。
答案 5 :(得分:0)
您的第一个查询正在使用错误的结果进行字符串比较。 您的第二个查询需要是:
WHERE create_date&gt; = TRUNC(to_date('04 / 10/2010','MM / DD / YYYY'))
或将hh:mi:ss添加到谓词中。这不是简单的工作'因为你要以与Oracle期望的不同的方式格式化日期。