【发布时间】: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