我是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');
答案 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'