Oracle BETWEEN 两个日期存储为 INT
Oracle BETWEEN two dates stored as INT
我是 DB 的新手,我在 Oracle 中有一个 table,日期存储为 INT,我的 SELECT 语句包含 TO_DATE() 所以我可以看到日期,然后我想添加一个 WHERE BETWEEN 并使用 "dates" 但我觉得必须有一种更清洁更有效的方法来做到这一点...我尝试对列使用 "alias" 但它给出了我有一个错误,说它需要一个整数,这就是为什么我在 WHERE 中再次有 TO_DATE() 的原因。
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');
它可以通过视图来完成,但由于您说数据库是只读的,因此在您的查询中它可能是 "nested" 有点像这样:
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
这样你只有一次丑陋的转换代码。
两件事。第一,使用 BETWEEN
对日期来说不是很好,因为日期不是完全离散的。最好使用类似的东西:
WHERE the_date >= TRUNC(start_dt)
AND the_date < TRUNC(end_dt) + 1;
第二,您似乎将日期存储为自 1/1/1970 以来经过的秒数?至少使用 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
日期只是一个养成的好习惯。我刚刚在我的数据库中的中型 table 上尝试了以下操作:
SELECT * FROM mytable
WHERE TRUNC(date_created) BETWEEN TRUNC(SYSDATE-2) AND TRUNC(SYSDATE-1);
以上给了我一个完整的 table 扫描,但 CPU 成本很高。然后我这样做了:
SELECT * FROM mytable
WHERE date_created >= TRUNC(SYSDATE-2)
AND date_created < TRUNC(SYSDATE);
这给了我对索引的范围扫描(因为 date_created
上有一个索引)和公平的 CPU 成本。我可以想象,对于具有数百万行的 "big" table,对比度会更大。
或者,可以在 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
上的索引,它会有一个优势。
我认为使用 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'
我是 DB 的新手,我在 Oracle 中有一个 table,日期存储为 INT,我的 SELECT 语句包含 TO_DATE() 所以我可以看到日期,然后我想添加一个 WHERE BETWEEN 并使用 "dates" 但我觉得必须有一种更清洁更有效的方法来做到这一点...我尝试对列使用 "alias" 但它给出了我有一个错误,说它需要一个整数,这就是为什么我在 WHERE 中再次有 TO_DATE() 的原因。
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');
它可以通过视图来完成,但由于您说数据库是只读的,因此在您的查询中它可能是 "nested" 有点像这样:
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
这样你只有一次丑陋的转换代码。
两件事。第一,使用 BETWEEN
对日期来说不是很好,因为日期不是完全离散的。最好使用类似的东西:
WHERE the_date >= TRUNC(start_dt)
AND the_date < TRUNC(end_dt) + 1;
第二,您似乎将日期存储为自 1/1/1970 以来经过的秒数?至少使用 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
日期只是一个养成的好习惯。我刚刚在我的数据库中的中型 table 上尝试了以下操作:
SELECT * FROM mytable
WHERE TRUNC(date_created) BETWEEN TRUNC(SYSDATE-2) AND TRUNC(SYSDATE-1);
以上给了我一个完整的 table 扫描,但 CPU 成本很高。然后我这样做了:
SELECT * FROM mytable
WHERE date_created >= TRUNC(SYSDATE-2)
AND date_created < TRUNC(SYSDATE);
这给了我对索引的范围扫描(因为 date_created
上有一个索引)和公平的 CPU 成本。我可以想象,对于具有数百万行的 "big" table,对比度会更大。
或者,可以在 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
上的索引,它会有一个优势。
我认为使用 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'