我在我们现有的一个存储过程中找到了以下查询。此查询用于记录两个日期时间值。
SELECT office
FROM officebudget
WHERE officeid = @officeid
AND (
(CONVERT(DATE, DateFrom) BETWEEN @wkstdate AND @wkenddate)
OR (CONVERT(DATE, DateTo) BETWEEN @wkstdate AND @wkenddate));
我重写了如下,
SELECT office
FROM officebudget
WHERE officeid = @officeid
AND (
(
bkto.DateFrom >= @wkstdate
AND bkto.DateFrom <= @wkenddate
)
OR (bkto.DateTo >= @wkstdate
AND bkto.DateTo <= @wkenddate)
);
两种情况都得到了相同的结果。但我需要知道上述两个查询都会产生的任何场景 不同的结果?
(P.S:DateFrom,DateTo,@ Wkstdate,@ Wkenddate是datetime
个字段)
答案 0 :(得分:1)
我怀疑您正在重构您的查询以使其成为可搜索的,并在列DateFrom
和DateTo
上使用可能的索引。
这些不会产生相同的结果,因为您的查询将省略wkenddate
的日期部分等于DateFrom
或DateTo
列值的日期部分的行。例如,我们说wkenddate = '20151005'
和您的专栏DateFrom = '20151005 15:30'
。第一个查询将包含此行,因为两个dateparts相等。并且您的第二个查询将省略此行'20151005 15:30' > '20151005'
。
考虑这些例子:
DECLARE @t TABLE(d DATETIME)
INSERT INTO @t VALUES
('20151001 10:30'),
('20151004 10:30'),
('20151005 10:30')
DECLARE @wkstdate DATE = '20151001', @wkenddate DATE = '20151005'
SELECT * FROM @t WHERE CAST(d AS DATE) BETWEEN @wkstdate AND @wkenddate
SELECT * FROM @t WHERE d >= @wkstdate AND d <= @wkenddate
SELECT * FROM @t WHERE d >= @wkstdate AND d < DATEADD(dd, 1, @wkenddate)
输出:
2015-10-01 10:30:00.000
2015-10-04 10:30:00.000
2015-10-05 10:30:00.000
2015-10-01 10:30:00.000
2015-10-04 10:30:00.000
2015-10-01 10:30:00.000
2015-10-04 10:30:00.000
2015-10-05 10:30:00.000
你应该重写为:
SELECT office
FROM officebudget
WHERE officeid = @officeid
AND (
(
bkto.DateFrom >= @wkstdate
AND bkto.DateFrom < dateadd(dd, 1 , @wkenddate)
)
OR (bkto.DateTo >= @wkstdate
AND bkto.DateTo < dateadd(dd, 1, @wkenddate))
);
答案 1 :(得分:0)
不同之处在于,在第一个查询中,您对已过滤的列(FateFrom和DateTo)使用了一个函数(CONVERT),如果它存在,则引擎无法使用该索引,因此第一个查询将倾向于慢一点
在第二个查询中,您手动输入了这样的日期:2015-09-30
。
最好像这样输入:20150930
,因为最后一种形式不依赖于服务器的区域,而第一种形式是。
答案 2 :(得分:0)
在某些情况下,它会给你不同的结果,或者最差的结果。
旧代码具有CONVERT
的原因是,开发人员希望确保他正在比较相同的确切数据类型,以避免错误或意外结果。请参阅下面的示例以进一步了解。
这个会返回FALSE
:就像给你不同的结果一样。
DECLARE @date1 DATETIME = GETDATE() --2015-10-05 16:15:54.780 , i used date today
DECLARE @date2 DATETIME = '20151005'
IF @date1 = @date2
BEGIN
SELECT 'TRUE'
END
ELSE
SELECT 'FALSE'
这个将返回TRUE
:类似于给你相同的结果
DECLARE @date1 DATETIME = CONVERT(DATE,GETDATE())
DECLARE @date2 DATETIME = CONVERT(DATE,'20151005')
IF @date1 = @date2
BEGIN
SELECT 'TRUE'
END
ELSE
SELECT 'FALSE'
希望我的示例可以帮助您分析您的代码,我的建议是先CONVERT
,然后再比较两个日期,以获得准确的结果。