我需要获取某个特定工作日的特定小时数据,直到10周。我工作的DB是Oracle。我想出了以下关于时间戳字段的条件:
TO_CHAR(hy.tstamp,'HH24')='10'
AND hy.tstamp > sysdate - 70
AND mod(extract ( day from sysdate-1) - extract ( day from hy.tstamp), 7) =0
有人告诉我“绝对没有围绕tstamp的功能”(出于性能原因?)。如何在时间戳字段中指定没有操作的条件?
答案 0 :(得分:4)
这听起来像抱怨性能的人从未听说过基于功能的索引。
Create index char_hy_stamp on my_table(to_char(hy.tstamp,'HH24'));
这应该避免全表扫描,这无疑是解释计划的一部分。一旦你获得了sqlfiddle功能,我们就可以从那里开始。
答案 1 :(得分:2)
如果您加入可接受范围的表,则可以过滤掉没有函数或函数索引的时间片。您可以像这样动态创建一个(请注意,您需要创建表的函数,但之后不需要它们):
SELECT
TRUNC(SYSDATE + 6) - (7 * LEVEL) + INTERVAL '10' HOUR AS StartAt,
TRUNC(SYSDATE + 6) - (7 * LEVEL) + INTERVAL '11' HOUR AS EndAt
FROM DUAL
CONNECT BY LEVEL <= 10
今天的日期是2013年5月8日,这将为您提供以下内容:
STARTAT ENDAT
------------------- -------------------
05/07/2013 10:00:00 05/07/2013 11:00:00
04/30/2013 10:00:00 04/30/2013 11:00:00
04/23/2013 10:00:00 04/23/2013 11:00:00
04/16/2013 10:00:00 04/16/2013 11:00:00
04/09/2013 10:00:00 04/09/2013 11:00:00
04/02/2013 10:00:00 04/02/2013 11:00:00
03/26/2013 10:00:00 03/26/2013 11:00:00
03/19/2013 10:00:00 03/19/2013 11:00:00
03/12/2013 10:00:00 03/12/2013 11:00:00
03/05/2013 10:00:00 03/05/2013 11:00:00
现在只需将其加入您的查询即可获得所需的时间片,并注意您不需要函数:
WITH TimeRanges AS (
SELECT
TRUNC(SYSDATE + 6) - (7 * LEVEL) + INTERVAL '10' HOUR AS StartAt,
TRUNC(SYSDATE + 6) - (7 * LEVEL) + INTERVAL '11' HOUR AS EndAt
FROM DUAL
CONNECT BY LEVEL <= 10
)
SELECT
... whatever ...
FROM your_table hy
INNER JOIN TimeRanges ON
hy.tstamp >= TimeRanges.StartAt AND
hy.tstamp < TimeRanges.EndAt
如果您的数据库人员了解对时间戳功能的过滤会导致性能下降(除非Woot4Moo指出,他们实现了功能索引),他们会理解用于创建时间表表的函数不会影响较大的查询