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-08-11 18:00:19.000
我的问题:
为什么第一个场景中的代码工作正常,而第二个场景中的代码不起作用?
为什么当我把实际范围设为BETWEEN'2012-08-11'EN'2012-08-11'时,第一个场景中的代码没有返回值...我怎样才能解决问题,我没有时间在范围/过滤期间考虑。我只被考虑约会。
答案 0 :(得分:2)
setDate
列上的最终索引。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的所有时间。当然,参数而不是文字仍然更好。
最后,真正的问题是如果你有这个查询的覆盖索引。时间序列,就像'时间表'表一样,几乎总是通过日期范围插入,因此(employeeID, setDate)
的聚簇索引可能是一个不错的选择。第二个最佳选择是同一个非聚集索引。
答案 1 :(得分:1)
使用CONVERT
并将值更改为DATETIME时,不会删除时间。因此与日期值的比较将不匹配。尝试以下内容以了解会发生什么
SELECT CONVERT(DateTime, t.setDate, 23)
FROM TimeSheet t
要从datetime中删除时间,请更改CONVERT
表达式,以便将结果转换为varchar数据类型
CONVERT(varchar, t.setDate, 23)