哪種方法可以在SQL Server上檢查當前月份的事件?爲什麼?在表SQL - 適用於當前月份的「where」子句
1)WHERE (DATEDIFF(month, EventTime, GETDATE())=0))
2)WHERE (YEAR(EventTime) = YEAR(GETDATE()) AND MONTH(EventTime) = MONTH(GETDATE()))
日期格式是即EventTime: 2011-11-30 15:68:25.000
哪種方法可以在SQL Server上檢查當前月份的事件?爲什麼?在表SQL - 適用於當前月份的「where」子句
1)WHERE (DATEDIFF(month, EventTime, GETDATE())=0))
2)WHERE (YEAR(EventTime) = YEAR(GETDATE()) AND MONTH(EventTime) = MONTH(GETDATE()))
日期格式是即EventTime: 2011-11-30 15:68:25.000
我無法使用探查器訪問SQL Server,因此我實際上無法提供詳細的答案。
問題基本上是關於哪一個允許最少的計算和最有效的索引使用。
使用字符串操作的變量具有最高的計算負載,並且根本不使用索引。所以我會跳過這些。這留下了四種常見的表達方式...
SELECT * FROM date_sargable
WHERE YEAR(value) = YEAR (getDate())
AND MONTH(value) = MONTH(getDate())
;
SELECT * FROM date_sargable
WHERE DATEDIFF(MONTH, value, getDate()) = 0
;
SELECT * FROM date_sargable
WHERE DATEDIFF(MONTH, 0, value) = DATEDIFF(MONTH, 0, getDate())
;
SELECT * FROM date_sargable
WHERE value >= DATEADD(MONTH, DATEDIFF(MONTH, 0, getDate()) , 0)
AND value < DATEADD(MONTH, DATEDIFF(MONTH, 0, getDate()) + 1, 0)
;
前三個使用INDEX SCAN,但最後一個使用INDEX SEEK。不同之處在於,查詢的格式允許優化器知道您想要特定範圍的數據,它在索引的一個塊中彼此相鄰,並且很容易找到該塊。
如果在查看執行計劃時,在一個版本中看到SEEK,而在另一個版本中看到SCAN,則更有可能從SEEK中受益。
在邏輯上,它們兩者都是。然而,我認爲第一個更簡單(一個條件而不是兩個),更容易理解並且更可能是可控的 - 所以我建議使用那個。
將連續期間的查詢寫爲明確的範圍條件。
http://use-the-index-luke.com/sql/where-clause/obfuscation/dates
因此,使用這樣的:
WHERE EventTime between <begin-of-month> and <end-of-month>
示例代碼可在同一頁面上,雖然這樣季報過濾:
爲什麼?使索引變得容易。
我不明白這是怎麼使事情變得更簡單。如果遵循這個例子,sql server需要執行4個查詢,而不僅僅是一個:執行quarter_begin兩次,quarter_end一次,最後執行c的實際查詢。雖然我沒有足夠的數據和可能的知識來正確地測試,但我會懷疑這實際上比OP提供的任何解決方案都要慢。除了速度問題之外 - 它確實使整個查詢變得更加複雜。 –
@Sascha Hennig - 函數(quater_end/begin)僅在實際查詢開始之前執行一次。如果您願意,也可以在應用程序中計算邊界日期(四捨五入結束/開始)。這並沒有帶來真正的性能差異。它使得索引變得更容易,因爲查詢可以在EventTime上使用直接索引,反過來,它將優於任何其他建議的變體。 –
約定:計算範圍的標量常量可能會使用「很多」文本,但幾乎不會使用任何查詢成本。數據庫中最大的成本通常是從磁盤讀取數據,這種方法可以確保讀取磁盤的最小數量,從而將冗餘讀取數量減少到接近於0(SEEKing)。替代品有許多冗餘讀取(SCANing)。 – MatBailie
如果你對此列的索引,那麼這兩個計算,因爲你沒有使用什麼列索引,但只有該指數的一部分
WHERE (DATEDIFF(month, EventTime, GETDATE())=0))
WHERE (YEAR(EventTime) = YEAR(GETDATE()) AND MONTH(EventTime) = MONTH(GETDATE()))
你是多大繞過指數使用這樣的事情
WHERE EventTime BETWEEN Cast (DATEADD(dd,-(DAY(GetDate())-1),GetDate()) as Date)
AND Cast (DATEADD(dd,-(DAY(DATEADD(mm,1,GetDate()))),DATEADD(mm,1,GetDate())) as Date)
更好您還可以使用與>=
和<=
同一概念的日期
一個提示使用to_char功能非常簡單,請看:
在日期例如:
2011-11-30 15:68:25.000
,你可以這樣做:
to_char(your_field,'MM')= 11
或系統日期的當前月份:
TO_CHAR(SYSDATE, 'MM')= 11
一個細節,TO_CHAR funcion由SQL語言支載,而不是由一個特定數據庫。
注意:數據類型DATETIME等沒有這種格式。這只是用來在屏幕上表示它們的格式,因爲我們人類不喜歡讀二進制文件等等。但是,如果它們實際上作爲字符串(NVARCHAR等)存儲在表中,則格式很重要,而且這個將嚴重打擊業績。 – MatBailie
@Dems啊,不,這是一個日期時間格式,不是varchar,不用擔心:) – yosh