【问题标题】:SQL: Using function in WHERE clause to convert date to datetimeSQL:在 WHERE 子句中使用函数将日期转换为日期时间
【发布时间】:2019-07-17 23:55:53
【问题描述】:

我有几个 SSRS 报告,用户必须在其中输入日期范围,并且无论是否包含时间戳,报告都需要正常工作。

我知道当SQL日期中不包含时间戳时,假定为'00:00:00.000' 所以在搜索订单WHERE orderDate BETWEEN '2019-01-01' AND '2019-01-02'时,例如不会包含2019-01-02的任何订单.我不能简单地使用DATEADD(d, 1, @endDate)CONVERT(date, orderDate),因为用户可能已经输入了他们自己的时间戳值,我希望保持真实。

如果用户输入一个简单的日期作为其日期范围的结束日期,我需要将其转换为日期时间值。由于我经常这样做,我创建了一个名为 dbo.DateToDatetime 的函数,它传入输入的日期,检查它是否有时间戳,如果没有,则添加自己的时间戳值 '23:59:59.997'

SELECT @datetime = CASE WHEN CONVERT(time, @date) = '0:0:0' THEN @date + '23:59:59.997' ELSE @date END

我经常在WHERE 子句中使用这个函数,如下所示:

WHERE orderDate BETWEEN @startDate AND dbo.DateToDatetime(@endDate)

我知道通常在WHERE 子句中使用函数是不好的做法,我担心这会对我的查询效率产生影响。有更好的解决方案吗?每次都输入 case 语句而不是使用函数会更好吗?

【问题讨论】:

  • 在表中的字段上使用 WHERE 子句时,功能很糟糕,尤其是在用于正在使用/定位的索引中的字段时,因为这些会导致对检查的每一行进行转换,如果针对索引,减少或消除索引的有用性。您使用它的方式(转换参数)不会显着影响查询的操作。
  • 请注意,使用 BETWEEN 时,您永远不会得到返回集中的最后一个值。因此,如果有人将结束时间设置为 10:15:00,知道存在具有该值的行,他们将不会看到返回该行。我可能会将您的功能更改为SELECT @datetime = CASE WHEN CONVERT(time, @date) = '0:0:0' THEN DATEADD(day, 1, @date) ELSE @date END,并改用WHERE orderDate >= @startDate AND orderDate < dbo.DateToDatetime(@endDate)
  • 声明一个新的DECLARE @END_DATE DATETIME = dbo.DateToDatetime(@endDate)

标签: sql sql-server datetime reporting-services where-clause


【解决方案1】:

我会建议使用 IF 语句是连接到 SSRS 参数的 SQL,该参数标记输入是否带有时间戳,然后使用正确格式的 where 子句执行选择的 SQL 选择语句。 此外 - 您可以在 SSRS 表达式中编写 SQL 语句并通过 exec @sql 将其“注入”到 where 子句

【讨论】:

    【解决方案2】:

    您可以使用强制转换来获得正确的输出

    CAST(orderDate as date) BETWEEN CAST(@startDate as date) and CAST(@endDate as date)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      相关资源
      最近更新 更多