【问题标题】:How to compare column values to declared variable如何将列值与声明的变量进行比较
【发布时间】:2020-11-07 09:12:40
【问题描述】:

我被问到这个面试问题。

--Without modifying the following code:

DECLARE @StartDateInput SMALLDATETIME = '1/1/2018',
            @EndDateInput SMALLDATETIME = '1/1/2018'

--Modify the following query so that it will return contacts modified at any time on January 1st, 2018
SELECT *
FROM   dbo.Contacts

我尝试了以下查询,但这不正确。我确定我也应该使用@EndDateInput 变量,但我不确定如何使用它。我也不认为这是处理这个问题的正确方法。

SELECT *
FROM dbo.Contacts
WHERE  ModifiedDate = SMALLDATETIME

【问题讨论】:

  • 我对他们的第一个问题是“ModifiedDate 列的数据类型是什么?” (我从措辞上怀疑它是一个带时间的类型,例如 DATETIME)
  • 是日期时间数据类型

标签: sql-server tsql declare


【解决方案1】:

看起来问题是在探究您对日期和日期时间类型的理解,即有时间的日期在没有时间的日期之后(如果甚至有这样的事情;大多数永恒的日期被认为是午夜相关的日期,也是一个时间。。同理,1.0和1是一样的,1.1在1.0之后)

我会使用一个范围:

SELECT *
FROM   dbo.Contacts
WHERE ModifiedDate >= @StartDateInput AND ModifiedDate < DATEADD(DAY, 1, @EndDateInput)

为什么?

  • 这适用于具有时间组件的日期时间。
  • 它不会修改行数据(总是一个坏主意,例如,每次查询时将一百万个日期时间转换为一个日期只是为了去掉时间 - 排除在列上使用索引并且是一种巨大的浪费资源)只是为了执行查询。
  • 它将两个@variables 相同所暗示的明显的“包含结束日期”转换为允许&lt; 的排他行为以包含性方式工作的形式(添加一天,然后获取少于第二天的行,因此包括 23:59:59.999999 ...)

我要说的是,严格来说,规范只要求一天的记录,这意味着根本不需要使用@EndDateInput。使用它似乎是合乎逻辑的,但可以争辩说,如果规范是该查询只会返回一天,则可以丢弃 @End 变量并在 @Start 上执行 DATEADD

【讨论】:

  • Cast( DateTimeColumn as Date ) 被查询优化器识别为一种特殊情况,并且可以使用索引查找,这是将函数应用于 where 或 @987654327 中的列的规则的例外之一@ 子句禁止使用索引查找。 This 回答探讨了一些选项。也就是说,我更喜欢half-open interval 的清晰性,如您的代码所示。
【解决方案2】:

它说“任何时间”的意思是考虑时间部分。使用 T-SQL 唯一可靠的方法是使用 >= 和

SELECT *
FROM dbo.Contacts
WHERE  ModifiedDate >= @StartDateInput and 
       ModifiedDate < dateadd(d, 1, @EndDateInput);

PS:@StartDateInput 和 @ENDDateInput 的初始声明并不可靠,可能偶然指向 2018 年 1 月 1 日。如果它是“2018 年 1 月 2 日”,那么 1 月 2 日到 2 月 1 日之间将是模棱两可的。更好地使用 ODBC 规范和\或 ISO 8601 字符串,例如“20180101”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多