两个DateTime字段之间的等效GETDATE(),其中两个都可以为NULL

时间:2012-06-26 21:27:17

标签: sql-server sql-server-2008 tsql sql-server-2008-r2

SELECT [Id]
      ,[DateOnline] --Nullable
      ,[DateOffline] --Nullable
      ,[PageId]
      ,[DownloadId]
      ,[Weight]
  FROM [DownloadPage]
  WHERE GETDATE() BETWEEN [DateOnline] AND [DateOffline]

相当于:

SELECT [Id]
      ,[DateOnline] --Nullable
      ,[DateOffline] --Nullable
      ,[PageId]
      ,[DownloadId]
      ,[Weight]
  FROM [DownloadPage]
  WHERE ([DateOnline] IS NULL OR [DateOnline] <= GETDATE())
  AND ([DateOffline] IS NULL OR [DateOffline] > GETDATE()) 

但是还要迎合NULL?

或者有更优雅的方式吗?

这里需要括号在哪里?

感谢。

编辑:

[DateOnline]和[DateOffline]都是DateTime类型

如果[DateOnline]为NULL,则逻辑为“立即在线”

如果[DateOffline]为NULL,则逻辑“永不脱机(一旦联机)”

对不起,我应该在我的问题中加入这个。

2 个答案:

答案 0 :(得分:3)

您可以使用COALESCE将空值转换为有意义的值。在这个例子中,我选择的默认值总是在有效范围内。

WHERE GETDATE() BETWEEN COALESCE([DateOnline] , '1900-01-01')
                    AND COALESCE([DateOffline], '2099-12-31')

演示:http://www.sqlfiddle.com/#!3/def09/1

答案 1 :(得分:3)

即使这些列上没有索引,作者的第二个查询也会获得更好的性能。如果有索引,那就没有问题......使用coalesce将禁用索引并执行表扫描而不是索引搜索(对性能非常糟糕)。

即使这些列上没有任何索引,“is null”也会返回一个常量...而在coalesce函数的情况下,仍然需要每次都计算NULL值。如果您的表格中包含NULL DateOnline和DateOffline,则不能忽略此性能泄漏。

在任何情况下,我都不会想到你在这种情况下使用合并的原因。

另外,我猜测(因为你正在检查日期范围)这两个日期是全部还是全部。您可能只需检查其中一个日期。

 WHERE ([DateOnline] IS NULL)
 OR GETDATE() BETWEEN [DateOnline] AND [DateOffline]