2015-10-05 75 views
0

我在我们现有的一个存储过程中找到了以下查询。此查询用于在两个日期时间值之间进行记录。在SQL Server中的两个日期时间之间获取记录

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) 
      ); 

我得到了这两种情况下相同的结果。但我需要知道在上述两个查询都会产生 不同结果的任何场景中?

(PS:DateFrom,DateTo,@Wkstdate,@Wkenddate是datetime字段)

+0

@wkstdate!='2015-09-30' –

+0

对不起,查询可以产生不同的结果。这是一个硬编码的价值。现在我编辑了问题 – bmsqldev

+0

'DateFrom'和'DateTo'是否有非零时间分量?如果是这样的话,那么您会错过第一个查询去除时间组件的转换(加上第一个查询中的转换目前已被破坏 - 当两个查询中的一个甚至不能完成时询问两个查询是否执行相同的操作编译) –

回答

1

我怀疑您正在重构您的查询以使其可用并在列DateFromDateTo上使用可能的索引。

这些将不会导致相同的结果,因为您的查询将忽略行的日期部分wkenddate等于datepart DateFromDateTo列值。例如,让我们说wkenddate = '20151005'和您的列DateFrom = '20151005 15:30'。由于两个日期部分相等,因此第一个查询将包含此行。而您的第二个查询将自'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)) 
      ); 
+0

但是Wkenddate是用<=条件检查的吗?那么它是否检查Wkenddate的相等和更短的日期? – bmsqldev

+0

我已经详细阐述了这个答案。 –

+0

因此,在比较之前将Datefrom和DateTo转换为Date是很好的做法吗? – bmsqldev

0

不同的是,在第一个查询,您的过滤列(FateFrom和dateTo)方法使用一个函数(CONVERT)那么如果引擎存在,引擎就不能使用它的索引,所以第一个查询往往会变慢。

在第二个查询中,您手动输入了如下所示的日期:2015-09-30。 最好是这样输入:20150930,因为这最后的形式不依赖于服务器的区域,而第一种形式是。

+0

我的任何一种情况都是将返回不同的结果集?(PS:我已经删除了硬编码的值) – bmsqldev

0

在某些情况下,它会给你不同的结果,或者最糟糕的NO结果。

旧代码有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它首先两个日期比较于前你得到确切的结果。

+0

我认为第一个查询将返回false :)。感谢您的建议 – bmsqldev

+0

@ user5359841,正如我对我的解释所说:) – Japongskie

相关问题