2010-10-10 93 views
1
SELECT COUNT(td.timeSheetID) FROM TimeSheet t 
INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID 
WHERE (CONVERT(DateTime, t.setDate, 23) BETWEEN '2012-08-10' AND '2012-08-12') 
AND t.employeeID = 300 

上述代碼返回我正在查找的值。然而,當我這樣做,我得到什麼:在表關於根據日期範圍提取記錄的問題

SELECT COUNT(td.timeSheetID) FROM TimeSheet t INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID 
    WHERE (CONVERT(DateTime, t.setDate, 23) = '2012-08-11') 
    AND t.employeeID = 300 

的setDate值看起來:

2012年8月11日18:00:19.000

我的問題:

  1. 爲什麼第一種情況下的代碼工作正常,而第二種情況下不起作用?

  2. 爲什麼第一種情況下的代碼沒有返回值,當我把實際範圍設置爲BETWEEN'2012-08-11'和'2012-08-11'...我該如何解決這個問題,我沒有時間在範圍/過濾期間考慮。我只考慮日期。

+0

什麼是格式23? – 2010-10-10 03:34:22

+0

YYYY-MM-DD ................ – 2010-10-10 04:01:23

回答

2
  • 不要編寫使用查詢列上的函數與常量進行比較。這使得它們不能使用SARG,並且setDate列上的最終索引不能使用。
  • 不要用文字在這裏你可以使用參數
  • 如果必須使用文字的日期時間,使用unseparated string format作爲不依賴於語言,是總是解釋爲ymd

結論:

SELECT COUNT(td.timeSheetID) FROM TimeSheet t 
INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID 
WHERE t.setDate BETWEEN @dateFrom AND @dateTo 
AND t.employeeID = @employeeId; 

或(較差):

SELECT COUNT(td.timeSheetID) FROM TimeSheet t 
INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID 
WHERE t.setDate BETWEEN '20120810' AND '20120812' 
AND t.employeeID = 300; 

至於你的問題,以掃描日期時間範圍內的 '天' 的最好辦法是表達當天作爲一個範圍:

SELECT COUNT(td.timeSheetID) FROM TimeSheet t 
INNER JOIN TimeSheetDetail td ON t.timeSheetID = td.timeSheetID 
WHERE t.setDate >= '20120811' AND t.setDate < '20120812' 
AND t.employeeID = 300; 

這將涵蓋20120811的所有小時。是當然,對參數而不是文字更好。

最後,真正的問題將是如果你有這個查詢的覆蓋索引。時間序列,就像'時間表'表,幾乎是總是 interogated日期範圍,因此聚集索引(employeeID, setDate)可能是一個不錯的選擇。第二個最佳選擇是同一個非聚集索引。

+0

Well Answered ...... – 2010-10-13 02:52:00

1

當您使用CONVERT並將該值更改爲DATETIME時,不會刪除該時間。所以與日期值的比較將不匹配。請嘗試以下方法看看會發生什麼

SELECT CONVERT(DateTime, t.setDate, 23) 
FROM TimeSheet t 

從日期時間下降時間改變CONVERT表達,這樣的結果轉換爲VARCHAR數據類型

CONVERT(varchar, t.setDate, 23)