2016-07-15 25 views
0

我必須選擇執行開始日期和結束日期之間的差異超過40分鐘的當天的日誌記錄。如何選擇兩個日期差異超過40分鐘的記錄?在Oracle中最好是

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:不一致的數據類型:預期數量得到DATE

回答

0

嘗試這樣

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 IW_MASTER_LOG as (select sysdate EXECUTION_START_DATE, sysdate+(1/24/60)*41 EXECUTION_ENDED_DATE from dual ) 

select IW_MASTER_LOG.* 
    from IW_MASTER_LOG 
WHERE TRUNC(EXECUTION_START_DATE)=TRUNC(SYSDATE) 
    AND to_number(EXECUTION_ENDED_DATE - EXECUTION_START_DATE) *24 * 60 > 40; 
+0

嗨АнатолийПредеин,感謝您的答覆。該查詢獲取了我想要的結果。你能詳細說明你如何處理會議紀要嗎? –

+0

是不是像..一天已經轉換爲小時,然後幾分鐘? –

+0

當你的日期減去日期這個回報是這兩個日期之間的天數,這就是爲什麼,我乘以24的價值獲得小時,然後在60分鐘獲得。 –

3

使用

EXECUTION_ENDED_DATE - EXECUTION_START_DATE > interval '40' minute 

此外,重寫THI病情

TRUNC(EXECUTION_START_DATE)=TRUNC(SYSDATE) 

到該一個

EXECUTION_START_DATE >= TRUNC(SYSDATE) and EXECUTION_START_DATE < TRUNC(SYSDATE)+1 

因爲前者條件阻止Oracle使用上EXECUTION_START_DATE列的索引並帶來了全表掃描

------- --------- 編輯 ----------------

INTERVAL子句工作s僅用於時間戳算術。
如果查詢返回ORA-00932: inconsistent datatypes: expected NUMBER got INTERVAL DAY TO SECOND,然後更改條件:

EXECUTION_ENDED_DATE - EXECUTION_START_DATE > 40/1440 

其中一個「魔術」號1440是在一天(24 * 60)分鐘數。


你能否詳細瞭解爲何阻止Oracle使用索引。

看一個簡單的例子。首先,讓我們建立一個測試dable充滿隨機數據:

CREATE INDEX my_execution_index ON IW_MASTER_LOG(EXECUTION_START_DATE); 

最後刷新表和索引的統計信息:

exec DBMS_STATS.gather_table_stats(user, 'IW_MASTER_LOG'); 

現在檢查

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_START_DATE列上創建索引此查詢的執行計劃:

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([email protected]!)>TRUNC([email protected]!)-1) 
    3 - access("EXECUTION_START_DATE">=TRUNC([email protected]!)-1 AND 
       "EXECUTION_START_DATE"<TRUNC([email protected]!)) 

上面的查詢使用索引


現在生成一個查詢,使用您的條件的計劃:

EXPLAIN PLAN FOR 
SELECT * FROM IW_MASTER_LOG 
WHERE trunc(EXECUTION_START_DATE) = trunc(sysdate) ; 

SELECT * FROM table(DBMS_XPLAN.DISPLAY); 
Plan hash value: 3290956462 

----------------------------------------------------------------------------------- 
| Id | Operation   | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
----------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |    | 741 | 91884 | 378 (1)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL| IW_MASTER_LOG | 741 | 91884 | 378 (1)| 00:00:01 | 
----------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter(TRUNC(INTERNAL_FUNCTION("EXECUTION_START_DATE"))=TRUNC(SYSDAT 
       [email protected]!)) 

俞看到,查詢執行全表掃描 - 在trunct函數阻止Oracle使用該索引。


正如@АнатолийПредеинsugested:

你可以爲這個列上創建功能指標如創建指數IW_MASTER_LOG(TRUNC(EXECUTION_START_DATE)) id_trunc_esd

他絕對我們來看看他的建議:

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([email protected]!)) 

完美 - 查詢使用新索引。您可以按照АнатолийПредеин的建議

但是這個指數是有限的 - 它只能服務於trunc(EXECUTION_START_DATE) = ...條件的查詢。它不能用於在某日期和此日期+ 10分鐘之間挑選行 - 我們仍然需要EXECUTION_START_DATE列上的普通索引。如果我問我的DBA是否可以創建兩個索引而不是一個索引,因爲我太懶惰了,並且在查詢中重寫了一個條件trunc(date),那麼他可能會在地毯上打電話給我。

+0

嗨krokodilko,你能詳細說明爲什麼它會阻止oracle使用索引。 另外,當我嘗試了'40'分鐘的時間間隔。它給了一個錯誤「ORA-00932:不一致的數據類型:預計NUMBER得到間隔日到第二」 –

+0

krokodilko嘗試說,如果您在查詢中使用TRUNC(EXECUTION_START_DATE)iit的EXECUTION_START_DATE列上沒有使用索引,因爲它的功能,可以在此列的函數上創建索引,如在IW_MASTER_LOG上創建索引id_trunc_esd(TRUNC(EXECUTION_START_DATE)) –

+0

感謝您的回覆。 :) –

0
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 - 當第二個參數省略時返回日期。

在以下數據集

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分鐘)

+0

嗨,彼得,感謝您的信息。但是,該查詢似乎沒有獲取預期的結果。我試着運行該查詢,它只返回2條記錄。但是我們確定有很多其他記錄超過40分鐘。 –

+0

嗨Arjun, 我更新了我的查詢 - 以前我忘了只爲今天的記錄過濾。現在開始日期必須是今天。如果流程運行並在第二天結束,則無關緊要。你也會得到結果。不幸的是,我沒有線索,爲什麼你檢索的行數比你認爲的要少,它應該起作用。 – peterpepo

+0

謝謝你的回覆:) –

相關問題