我有2個SQL腳本。其中一個是這樣的:在兩個日期之間查找日期(最佳做法)
"Date" > '2014-04-11' AND "Date" <= '2014-04-12'
另外一個是這樣的:
"Date" BETWEEN '2014-04-11' AND '2014-04-12'
現在我不知道是否有任何具體的最佳實踐,其中一個原因做了另一種,如果他們中的一個是更好的出於某種明顯的原因,我錯過了沿途的某個地方。
我有2個SQL腳本。其中一個是這樣的:在兩個日期之間查找日期(最佳做法)
"Date" > '2014-04-11' AND "Date" <= '2014-04-12'
另外一個是這樣的:
"Date" BETWEEN '2014-04-11' AND '2014-04-12'
現在我不知道是否有任何具體的最佳實踐,其中一個原因做了另一種,如果他們中的一個是更好的出於某種明顯的原因,我錯過了沿途的某個地方。
您正在尋求最佳實踐。我認爲,以下爲最佳實踐:
"Date" >= DATE '2014-04-11' AND "Date" < DATE '2014-04-12' + 1
首先,請注意使用DATE
關鍵字。您的問題是關於日期,但您使用的是Oracle不直接支持的日期格式。令人高興的是,Oracle支持符合ISO標準格式的ANSI標準DATE
關鍵字。
其次,我添加了一個+1
,以便您可以看到時間段的結束,這可能是您想要在代碼中看到的內容。它不應該影響性能,因爲+ 1
是常量。
第三,日期常量具有時間分量。如果沒有指定,則是在日期的午夜。因此,表達式:
"Date" BETWEEN '2014-04-11' AND '2014-04-12'
是真的:
"Date" >= TIMESTAMP '2014-04-11 00:00:00' AND "Date" <= TIMESTAMP '2014-04-12 00:00:00'
也就是說,從後來的日期恰好一個時間包括,在午夜的第一瞬間。這通常不是你想要的。 Oracle通過兩種方式使此問題變得更糟:
date
數據類型包含一個時間組件。date
值的默認方式沒有時間分量。所以,爲了安全,請使用以下規則:
between
。>=
。<
第二。Aaron Bertrand在這個話題上有一個blog。雖然它特別針對SQL Server,但許多想法都適用於Oracle - 尤其是因爲Oracle中的date
數據類型包含時間。
「日期」是抽象的,但由於在這種情況下原始的列名沒有意義,我冒昧地將它改爲更可讀的東西,儘管不太正確。 – 2014-09-01 14:32:31
SQL> create table date_tab as select sysdate + level d from dual connect by rownum < 10;
Table created.
之間使用:
SQL> set autotrace traceonly
SQL> select * from date_tab where d between sysdate + 1 and sysdate + 3;
Execution Plan
----------------------------------------------------------
Plan hash value: 290508398
...
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter([email protected]!+1<[email protected]!+3)
2 - filter("D">[email protected]!+1 AND "D"<[email protected]!+3)
使用日期間隔:
SQL> select * from date_tab where d > sysdate + 1 and d <= sysdate + 3;
Execution Plan
----------------------------------------------------------
Plan hash value: 290508398
...
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter([email protected]!+1<[email protected]!+3)
2 - filter("D">[email protected]!+1 AND "D"<[email protected]!+3)
正如你所看到的,Oracle優化重寫between
謂詞"D">[email protected]!+1 AND "D"<[email protected]!+3
所以如果你使用第二個變種Oracle執行比第一個變體少一步。
這兩個查詢不是同義詞。 「BETWEEN」包含兩個參數。我建議閱讀這兩篇文章; [BETWEEN和魔鬼有什麼共同之處?](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do-between-and-the-devil-have-in-common .aspx)和[壞習慣踢:錯誤處理日期/範圍查詢](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/16/bad-habits-to-kick-mishandling-日期範圍-queries.aspx)。雖然是爲SQL Server編寫的,但許多參數仍然適用於Oracle。 – GarethD 2014-09-01 12:20:45
不*相當*同義;第一個有'>'而不是'> =',這可能是一個錯誤。雖然你想要找到哪些數據,但並不完全清楚。 (我也建議你不要使用帶引號的標識符或隱式日期轉換,但兩者都不在問題的範圍之內)。 – 2014-09-01 12:26:05
感謝您的鏈接,我一直在尋找這個主題,但我的「GoogleFu」在這件事上沒有發現任何東西。 – 2014-09-01 14:33:38