Sql 如何选择两个日期相差超过40分钟的记录?最好用甲骨文
我必须选择当天的日志记录,其中执行开始日期和结束日期之间的差异超过40分钟Sql 如何选择两个日期相差超过40分钟的记录?最好用甲骨文,sql,oracle,date,Sql,Oracle,Date,我必须选择当天的日志记录,其中执行开始日期和结束日期之间的差异超过40分钟 select * from iwdata.IW_MASTER_LOG WHERE TRUNC(EXECUTION_START_DATE)=TRUNC(SYSDATE) AND (EXECUTION_START_DATE-EXECUTION_ENDED_DATE) >to_date('40','mi'); 但是这个查询给了我一个错误 ORA-00932:不一致的数据类型:预期的数字获取日期 with a as
select * from iwdata.IW_MASTER_LOG
WHERE TRUNC(EXECUTION_START_DATE)=TRUNC(SYSDATE)
AND (EXECUTION_START_DATE-EXECUTION_ENDED_DATE) >to_date('40','mi');
但是这个查询给了我一个错误
ORA-00932:不一致的数据类型:预期的数字获取日期
with a as ( select sysdate sd, sysdate+(1/24/60)*39 ed from dual)
-- in with sysdate and sysdate + 39 minute
select to_char(sd,'dd.mm.yyyy hh24:mi:ss'),
to_char(ed,'dd.mm.yyyy hh24:mi:ss'),
to_number(ed-sd) *24 * 60
from a
where to_number(ed-sd) *24 * 60 < 40
像这样试试
with a as ( select sysdate sd, sysdate+(1/24/60)*39 ed from dual)
-- in with sysdate and sysdate + 39 minute
select to_char(sd,'dd.mm.yyyy hh24:mi:ss'),
to_char(ed,'dd.mm.yyyy hh24:mi:ss'),
to_number(ed-sd) *24 * 60
from a
where to_number(ed-sd) *24 * 60 < 40
使用
此外,请重写此条件
TRUNC(EXECUTION_START_DATE)=TRUNC(SYSDATE)
这一个
EXECUTION_START_DATE >= TRUNC(SYSDATE) and EXECUTION_START_DATE < TRUNC(SYSDATE)+1
其中“神奇”数字1440是一天中的分钟数(24*60)
你能详细解释一下为什么它阻止oracle使用索引吗 请看一个简单的示例。首先,让我们创建一个充满随机数据的测试:
CREATE TABLE IW_MASTER_LOG AS
SELECT sysdate - 500*dbms_random.value as EXECUTION_START_DATE,
t.*
FROM all_objects t;
SELECT count(*) FROM IW_MASTER_LOG;
COUNT(*)
----------
74130
接下来在EXECUTION\u START\u DATE
列上创建索引:
CREATE INDEX my_execution_index ON IW_MASTER_LOG( EXECUTION_START_DATE );
最后刷新表和索引统计信息:
exec DBMS_STATS.gather_table_stats( user, 'IW_MASTER_LOG' );
现在检查此查询的执行计划:
EXPLAIN PLAN FOR
SELECT * FROM IW_MASTER_LOG
WHERE EXECUTION_START_DATE >= trunc( sysdate ) - 1
AND EXECUTION_START_DATE < trunc( sysdate );
SELECT * FROM table( DBMS_XPLAN.DISPLAY );
Plan hash value: 3519959109
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 149 | 18476 | 152 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| IW_MASTER_LOG | 149 | 18476 | 152 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | MY_EXECUTION_INDEX | 149 | | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TRUNC(SYSDATE@!)>TRUNC(SYSDATE@!)-1)
3 - access("EXECUTION_START_DATE">=TRUNC(SYSDATE@!)-1 AND
"EXECUTION_START_DATE"<TRUNC(SYSDATE@!))
正如您所看到的,查询执行完整的表扫描-函数trunct
阻止Oracle使用该索引
正如所建议的那样: 您可以在函数上为此列创建索引,如创建索引 IW主日志上的id\u trunc\u esd(trunc(执行开始日期)) 他完全正确,让我们看看他的建议:
CREATE INDEX another_index ON IW_MASTER_LOG( TRUNC(EXECUTION_START_DATE) );
exec DBMS_STATS.gather_table_stats( user, 'IW_MASTER_LOG' );
EXPLAIN PLAN FOR
SELECT * FROM IW_MASTER_LOG
WHERE trunc(EXECUTION_START_DATE) = trunc( sysdate ) ;
SELECT * FROM table( DBMS_XPLAN.DISPLAY );
Plan hash value: 1627571743
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 148 | 19536 | 142 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| IW_MASTER_LOG | 148 | 19536 | 142 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | ANOTHER_INDEX | 148 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(TRUNC(INTERNAL_FUNCTION("EXECUTION_START_DATE"))=TRUNC(SYSDATE@!))
完美-查询使用新索引。您可以按照АааааПааааааааааа
但是这个索引是有限的-它只能服务于带有trunc(EXECUTION\u START\u DATE)=…
条件的查询。例如,它不能用于选择某个日期和此日期+10分钟之间的行-我们仍然需要在EXECUTION\u START\u date
列上使用普通索引。如果我问我的DBA是否可以创建两个索引而不是一个,因为我太懒了,无法在查询中重写一个条件trunc(date)
,那么他可能会在地毯上给我打电话。使用
WITH IW_MASTER_LOG AS
(SELECT SYSDATE AS EXECUTION_START_DATE,
SYSDATE AS EXECUTION_END_DATE
FROM DUAL
UNION ALL
SELECT SYSDATE, SYSDATE+1/24/60*30 FROM DUAL
UNION ALL
SELECT SYSDATE, SYSDATE+1/24/60*41 FROM DUAL
)
SELECT *
FROM IW_MASTER_LOG
WHERE (EXECUTION_END_DATE-EXECUTION_START_DATE)>=1/24/60*40
AND TRUNC(EXECUTION_START_DATE) = TRUNC(SYSDATE); --started today
此外,请重写此条件
TRUNC(EXECUTION_START_DATE)=TRUNC(SYSDATE)
这一个
EXECUTION_START_DATE >= TRUNC(SYSDATE) and EXECUTION_START_DATE < TRUNC(SYSDATE)+1
其中“神奇”数字1440是一天中的分钟数(24*60)
你能详细解释一下为什么它阻止oracle使用索引吗 请看一个简单的示例。首先,让我们创建一个充满随机数据的测试:
CREATE TABLE IW_MASTER_LOG AS
SELECT sysdate - 500*dbms_random.value as EXECUTION_START_DATE,
t.*
FROM all_objects t;
SELECT count(*) FROM IW_MASTER_LOG;
COUNT(*)
----------
74130
接下来在EXECUTION\u START\u DATE
列上创建索引:
CREATE INDEX my_execution_index ON IW_MASTER_LOG( EXECUTION_START_DATE );
最后刷新表和索引统计信息:
exec DBMS_STATS.gather_table_stats( user, 'IW_MASTER_LOG' );
现在检查此查询的执行计划:
EXPLAIN PLAN FOR
SELECT * FROM IW_MASTER_LOG
WHERE EXECUTION_START_DATE >= trunc( sysdate ) - 1
AND EXECUTION_START_DATE < trunc( sysdate );
SELECT * FROM table( DBMS_XPLAN.DISPLAY );
Plan hash value: 3519959109
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 149 | 18476 | 152 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| IW_MASTER_LOG | 149 | 18476 | 152 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | MY_EXECUTION_INDEX | 149 | | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TRUNC(SYSDATE@!)>TRUNC(SYSDATE@!)-1)
3 - access("EXECUTION_START_DATE">=TRUNC(SYSDATE@!)-1 AND
"EXECUTION_START_DATE"<TRUNC(SYSDATE@!))
正如您所看到的,查询执行完整的表扫描-函数trunct
阻止Oracle使用该索引
正如所建议的那样: 您可以在函数上为此列创建索引,如创建索引 IW主日志上的id\u trunc\u esd(trunc(执行开始日期)) 他完全正确,让我们看看他的建议:
CREATE INDEX another_index ON IW_MASTER_LOG( TRUNC(EXECUTION_START_DATE) );
exec DBMS_STATS.gather_table_stats( user, 'IW_MASTER_LOG' );
EXPLAIN PLAN FOR
SELECT * FROM IW_MASTER_LOG
WHERE trunc(EXECUTION_START_DATE) = trunc( sysdate ) ;
SELECT * FROM table( DBMS_XPLAN.DISPLAY );
Plan hash value: 1627571743
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 148 | 19536 | 142 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| IW_MASTER_LOG | 148 | 19536 | 142 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | ANOTHER_INDEX | 148 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(TRUNC(INTERNAL_FUNCTION("EXECUTION_START_DATE"))=TRUNC(SYSDATE@!))
完美-查询使用新索引。您可以按照АааааПааааааааааа
但是这个索引是有限的-它只能服务于带有trunc(EXECUTION\u START\u DATE)=…
条件的查询。例如,它不能用于选择某个日期和此日期+10分钟之间的行-我们仍然需要在EXECUTION\u START\u date
列上使用普通索引。如果我问我的DBA是否可以创建两个索引而不是一个,因为我太懒了,无法在查询中重写一个条件trunc(date)
,那么他可能会打电话给我
WITH IW_MASTER_LOG AS
(SELECT SYSDATE AS EXECUTION_START_DATE,
SYSDATE AS EXECUTION_END_DATE
FROM DUAL
UNION ALL
SELECT SYSDATE, SYSDATE+1/24/60*30 FROM DUAL
UNION ALL
SELECT SYSDATE, SYSDATE+1/24/60*41 FROM DUAL
)
SELECT *
FROM IW_MASTER_LOG
WHERE (EXECUTION_END_DATE-EXECUTION_START_DATE)>=1/24/60*40
AND TRUNC(EXECUTION_START_DATE) = TRUNC(SYSDATE); --started today
Oracle日期表示为天数的分数,这意味着什么
1 - day
1/24 - hour
1/24/60 - minute
1/24/60*40 - 40 mins
TRUNC-忽略第二个参数返回日期时
在我的结果中使用WITH子句将在以下数据集中显示
07.15.2016 14:13:54 | 07.15.2016 14:13:54
07.15.2016 14:13:55 | 07.15.2016 14:43:55
07.15.2016 14:13:56 | 07.15.2016 14:54:56
查询只返回最后一条记录(需要什么,因为41分钟)
Oracle日期表示为天数的分数,这意味着什么
1 - day
1/24 - hour
1/24/60 - minute
1/24/60*40 - 40 mins
TRUNC-忽略第二个参数返回日期时
在我的结果中使用WITH子句将在以下数据集中显示
07.15.2016 14:13:54 | 07.15.2016 14:13:54
07.15.2016 14:13:55 | 07.15.2016 14:43:55
07.15.2016 14:13:56 | 07.15.2016 14:54:56
查询只返回最后一条记录(需要什么,因为需要41分钟)Hi krokodilko,您能否详细说明为什么它阻止oracle使用索引。我也试过40分钟的间歇时间。它给出了一个错误“ORA-00932:不一致的数据类型:预期的数字得到了间隔天数到秒”krokodilko试图说,如果您在查询中使用TRUNC(执行开始日期),它不会在执行开始日期列上使用索引,因为它是一个函数,您可以在该列上创建索引,就像在IW主日志上创建索引id TRUNC esd一样(TRUNC(EXECUTION\u START\u DATE))感谢您的回复。:)嗨,krokodilko,您能详细解释一下为什么它阻止oracle使用索引吗。我也试过40分钟的间歇时间。它给出了一个错误“ORA-00932:不一致的数据类型:预期的数字得到了间隔天数到秒”krokodilko试图说,如果您在查询中使用TRUNC(执行开始日期),它不会在执行开始日期列上使用索引,因为它是一个函数,您可以在该列上创建索引,就像在IW主日志上创建索引id TRUNC esd一样谢谢你的回复。嗨,彼得,谢谢你提供的信息。但是,查询似乎无法获取预期的结果。我试着运行那个查询,它只返回了2条记录。但是我确信还有很多超过40分钟的记录。嗨,Arjun,我已经更新了我的查询-以前我忘了只过滤今天的记录。现在开始日期必须是今天。如果这个过程在第二天运行并结束,那没关系。你也会得到结果的。不幸的是,我一点也不知道,为什么你检索的行数少于你认为应该检索的行数,应该可以。谢谢你的回答:)嗨,彼得,谢谢你提供的信息。但是,查询似乎无法获取预期的结果。我试着运行那个查询,它只返回了2条记录。但是我确信还有很多超过40分钟的记录。嗨,Arjun,我已经更新了我的查询-以前我忘了只过滤今天的记录。现在开始日期必须是今天。如果这个过程在第二天运行并结束,那没关系。你会得到结果的