Oracle BETWEEN存储为INT的两个日期

时间:2015-02-25 19:45:22

标签: sql oracle date int between

我是DB的新手,我在Oracle中有一个表,日期存储为INT,我的SELECT语句包括TO_DATE()所以我可以看到日期,然后我想添加WHERE BETWEEN并使用“日期”但我觉得必须有一个更干净,更有效的方法来做到这一点...我尝试使用列的“别名”,但它给我一个错误,说它期望一个整数,这就是为什么我再次有TO_DATE()在WHERE。

SELECT to_date('1-Jan-1970 00:00:00','dd-mon-yyyy hh24:mi:ss')
  + IRF.START_DATE_TIME_KEY/60/60/24) AS START_DATE_TIME_KEY
 WHERE to_date('1-Jan-1970 00:00:00','dd-mon-yyyy hh24:mi:ss')
  + (IRF.START_DATE_TIME_KEY/60/60/24) 
BETWEEN TO_DATE('20-Feb-2015 00:00:01','dd-mon-yyyy hh24:mi:ss') 
    AND TO_DATE('20-Feb-2015 23:59:59','dd-mon-yyyy hh24:mi:ss');

3 个答案:

答案 0 :(得分:2)

夫妻俩。一,使用BETWEEN对日期来说并不是那么好,因为日期并不是完全离散的。最好使用类似的东西:

WHERE the_date >= TRUNC(start_dt)
  AND the_date < TRUNC(end_dt) + 1;

二,看起来您将日期存储为自1970年1月1日以来经过的秒数?你可能最好至少使用ANSI日期文字和间隔:

SELECT DATE'1970-01-01' + NUMTODSINTERVAL(ifs_start_date_time_key, 'SECOND')

您可以使用上述别名,但除非您使用子查询,否则无法在WHERE子句中引用它。所以把所有这些放在一起:

SELECT start_date_time_key FROM (
    SELECT DATE'1970-01-01' + NUMTODSINTERVAL(irf.start_date_time_key, 'SECOND') AS start_date_time_key
      FROM mytable irf
) WHERE start_date_time_key >= DATE'2015-02-20'
    AND start_date_time_key < DATE'2015-02-20' + INTERVAL '1' DAY; -- or just DATE'2015-02-20' + 1;

有人在评论中询问为什么不将BETWEEN与日期一起使用。好吧,在这种情况下,它几乎肯定不重要,因为当start_date_time_key转换为DATE时,它不会成为索引,但它会在DATE列上有索引的情况下,因此避免日期BETWEEN只是一个很好的习惯。我只是在我的数据库中的中型桌子上尝试了以下内容:

SELECT * FROM mytable
 WHERE TRUNC(date_created) BETWEEN TRUNC(SYSDATE-2) AND TRUNC(SYSDATE-1);

上面给了我一张高CPU成本的全表扫描。然后我这样做了:

SELECT * FROM mytable
 WHERE date_created >= TRUNC(SYSDATE-2)
   AND date_created < TRUNC(SYSDATE);

这给了我一个关于索引的范围扫描(因为date_created上有一个索引)和一个公平的CPU成本。我可以想象一个&#34;大&#34;对比度会更大。有数百万行的表。

或者,可以在DATE列上放置基于函数的索引(例如,TRUNC(mydate)),但如果您的日期值也包含时间部分,则无法帮助您。只需回避BETWEEN - 使用>=<并不是更多的打字。


另一个想法让我印象深刻。如果列IRF.START_DATE_TIME_KEY本身已编入索引,那么将日期转换为类似的整数并使用它们可能会更好。

SELECT DATE'1970-01-01' + NUMTODSINTERVAL(irf.start_date_time_key, 'SECOND') AS start_date_time_key
  FROM mytable irf
 WHERE irf.start_date_time_key >= (DATE'2015-02-20' - DATE'1970-01-01') * 86400
   AND irf.start_date_time_key < (DATE'2015-02-20' + 1 - DATE'1970-01-01') * 86400

它并不漂亮,但如果有一个索引,它会有IRF.START_DATE_TIME_KEY使用索引的优势。

答案 1 :(得分:0)

可以通过视图来完成,但是因为你说数据库是只读的,所以它可以是#34;嵌套的#34;在你的查询中有点像这样:

select REAL_DATE_COL
from
(select *, --code to convert int date to real date-- as REAL_DATE_COL
from MY_TABLE)
where REAL_DATE_COL between date1 and date2

这样你只需要一次丑陋的转换代码。

答案 2 :(得分:0)

我认为使用date关键字可以让您的代码更清晰:

SELECT (DATE '1970-01-01' + IRF.START_DATE_TIME_KEY/60/60/24) AS START_DATE_TIME_KEY
FROM . . .
WHERE DATE '1970-01-01' + IRF.START_DATE_TIME_KEY/60/60/24) BETWEEN DATE '2015-02-20' AND '2015-02-20'