2010-03-03 125 views
46

我正在使用oracle數據庫。我想執行一個查詢來檢查兩個日期之間的數據。Oracle date「Between」查詢

NAME    START_DATE  
------------- ------------- 
Small Widget  15-JAN-10 04.25.32.000000 PM  
Product 1   17-JAN-10 04.31.32.000000 PM 



select * from <TABLENAME> where start_date 
BETWEEN '15-JAN-10' AND '17-JAN-10' 

但我沒有從上面的查詢得到任何結果。我想我必須使用「like」和「%」。但我不知道在哪裏使用它們。請在此點亮一些燈。

在此先感謝。

回答

74

從輸出來看,它看起來像你將START_DATE定義爲時間戳。如果這是一個正常的日期,Oracle將能夠處理隱式轉換。但是,因爲它不是你需要明確地將這些字符串轉換爲日期。

SQL> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss' 
    2/

Session altered. 

SQL> 
SQL> select * from t23 
    2 where start_date between '15-JAN-10' and '17-JAN-10' 
    3/

no rows selected 

SQL> select * from t23 
    2 where start_date between to_date('15-JAN-10') and to_date('17-JAN-10') 
    3/

WIDGET       START_DATE 
------------------------------ ---------------------- 
Small Widget     15-JAN-10 04.25.32.000  

SQL> 

但是我們仍然只得到一行。這是因爲START_DATE有一個時間元素。如果我們不指定時間組件,Oracle默認它是午夜。這是罰款的BETWEEN的一面,但不是爲直到方:

SQL> select * from t23 
    2 where start_date between to_date('15-JAN-10') 
    3      and to_date('17-JAN-10 23:59:59') 
    4/

WIDGET       START_DATE 
------------------------------ ---------------------- 
Small Widget     15-JAN-10 04.25.32.000 
Product 1      17-JAN-10 04.31.32.000 

SQL> 

編輯

如果你不能在時間成分通過有一對夫婦的選擇。一種是改變WHERE子句從標準中刪除了時間元素:

where trunc(start_date) between to_date('15-JAN-10') 
          and to_date('17-JAN-10') 

這可能會對性能產生影響,因爲它在不夠格START_DATE任何B樹索引。你需要建立一個基於函數的索引。

或者你可以在時間元素添加到日期代碼:

where start_date between to_date('15-JAN-10') 
        and to_date('17-JAN-10') + (86399/86400) 

因爲這些問題很多人喜歡通過檢查日期界限這樣來避免使用between

where start_date >= to_date('15-JAN-10') 
and start_date < to_date('18-JAN-10') 
+0

我無法通過時間唯一的日期。 – 2010-03-03 09:18:01

+0

哇,它工作的很好APC ...非常感謝您的支持 – 2010-03-03 12:18:47

+0

@APC在ORACLE 11中工作得像魅力G – Alex 2016-08-05 15:10:33

20

你需要轉換的實際日期,而不是字符串,試試這個:

SELECT * 
FROM <TABLENAME> 
WHERE start_date BETWEEN TO_DATE('2010-01-15','YYYY-MM-DD') AND TO_DATE('2010-01-17', 'YYYY-MM-DD'); 

編輯處理的格式規定:

SELECT * 
FROM <TABLENAME> 
WHERE start_date BETWEEN TO_DATE('15-JAN-10','DD-MON-YY') AND TO_DATE('17-JAN-10','DD-MON-YY'); 
+0

感謝您的迅速回復。但是我以這種格式「17-JAN-10」從動作文件中獲取From和To date。所以它是這樣的: SELECT \t * FROM uson_assetaccess WHERE accessdate BETWEEN TO_DATE('17 -FEB-10','dd-MMM-yy')和TO_DATE('17 -FEB-10','dd-MMM- YY'); 但是我得到一個錯誤:ORA-01821:日期格式無法識別 – 2010-03-03 06:54:27

+0

您只需使用不同的格式說明符,用「MON」替換「MMM」,請參閱我的編輯。 – 2010-03-03 06:57:30

+0

再次感謝您立即回覆。但我已經使用該查詢但現在日期格式錯誤消失了。現在我沒有發現數據錯誤,即使數據在表中。我認爲在桌上的日期與時間有關,但我們僅以日期發送。是因爲這個原因嗎?請澄清 – 2010-03-03 07:02:28

3

正如APC正確指出的那樣,start_date列看起來像是TIMESTAMP,但它也可能是TIMESTAMP WITH LOCAL TIMEZONE或TIMESTAMP WITH TIMEZONE數據類型。如果您的數據庫服務器與您自己處於不同的時區,這些可能會影響您對數據執行的任何查詢。但是,讓我們保持簡單並假設您與服務器位於同一時區。首先,爲了給您信心,請檢查start_date是否爲TIMESTAMP數據類型。

使用SQLPlus DESCRIBE命令(或IDE中的等效項)來驗證此列是否爲TIMESTAMP數據類型。

DESCRIBE MYTABLE

應該報告:

Name  Null? Type 
----------- ----- ------------ 
NAME    VARHAR2(20) 
START_DATE  TIMESTAMP 

如果報告爲一個類型= TIMESTAMP,那麼你可以用最簡單的TO_TIMESTAMP日期轉換查詢您的日期範圍,一個需要沒有參數(或圖片)。

我們使用TO_TIMESTAMP確保優化程序考慮START_DATE列中的任何索引。 APC的回答還指出,基於函數的索引可能已經創建在該列上,並且會影響SQL謂詞,但我們無法對此查詢中的評論發表評論。如果您想知道如何找出已應用於表格的索引,請發佈另一個問題,我們可以分別回答。

因此,假設有在起始日期指數,這是一個TIMESTAMP數據類型和您想要的優化考慮它,你的SQL是:

select * from mytable where start_date between to_timestamp('15-JAN-10') AND to_timestamp('17-JAN-10')+.9999999 

+.999999999非常接近,但是,這不是」 t相當於1,因此17-JAN-10的轉換將盡可能接近午夜,因此您查詢時會返回兩行。

數據庫將看到從15-JAN-10之間爲00:00:00:000000017-JAN-10 23:59:59:99999,因此將包括所有的日期從15日無論時間戳的時間組件如何。

希望有所幫助。

Dazzer

1

日期查詢

SELECT * 
    FROM emp 
    WHERE HIREDATE between to_date (to_char(sysdate, 'yyyy') ||'/09/01', 'yyyy/mm/dd') 
    AND to_date (to_char(sysdate, 'yyyy') + 1|| '/08/31', 'yyyy/mm/dd'); 
1

之間下面的查詢,也可以使用:

select * 
    from t23 
where trunc(start_date) between trunc(to_date('01/15/2010','mm/dd/yyyy')) and trunc(to_date('01/17/2010','mm/dd/yyyy')) 
+2

如果一個表很大並且日期列被索引,那麼應該避免使用'to_date(' 01/15/2010','mm/dd/yyyy')和to_date('01/17/2010','mm/dd/yyyy')+ 1'。 – Dmitry 2015-03-30 13:47:28