在 DATEDIFF() 中编写 Case 语句的更好方法?

A better way to write a Case statement in DATEDIFF()?

我编写了一个查询来查找记录处于特定状态的天数。我的查询工作正常,但我只想知道是否有更有效的编写方法。我的起始数据如下所示:

   MemberID StatusDate1   StatusDate2   StatusDate3   StatusDate4
     77         2017-01-06    2017-03-30     NULL         2017-04-13
     88         NULL          NULL           2017-07-19   NULL

最终结果如下所示:

   MemberID  StatusDate1   StatusDate2   StatusDate3   StatusDate4
     77         83             14            NULL          116
     88        NULL            NULL            19          NULL

问题是如果状态日期为 NULL,那么我需要找到下一个填充日期并使用它。我正在使用 Case 语句进行计算,虽然它确实有效,但我一直认为必须有比我编写它的方式更好的方法:

    Select *, DATEDIFF(dd, StatusDate1, case when StatusDate2 is not null then StatusDate2,
                                             when StatusDate2 is null then StatusDate3,
                                             when StatusDate3 is not null then StatusDate3,
                                             when StatusDate3 is null then StatusDate4,
                                             when StatusDate4 is null then getdate())end) as NewStatusDate1

我正在为所有 4 个状态日期写这篇文章。有没有更简单的写法?

我不知道这样是否更高效,但是这样写和读起来肯定更容易:

SELECT *,
       DATEDIFF(day, StatusDate1, 
                COALESCE(StatusDate2, StatusDate3, StatusDate4, GETDATE()
               ) as NewStatusDate1

我不确定您为什么将整数结果称为 "new status date"。您确定不想要 DATEADD() 吗?

作为旁注,请注意 datediff 测量 'boundary crossings',而不是间隔的长度。

取这两个时间点:

1 月 1 日 23:59

1 月 2 日 00:01

在此场景中,时间段为两分钟。

根据您的需要,应该算一天吗?

Datediff 将 return 1(当您使用 dd 或等效项时),因为第二个日期的日期部分比第一个日期多一个。

如果您的数据类型比简单的日期更精确,而不是您希望它四舍五入 - 例如超过十二小时被认为是一天 - 您将需要一种稍微不同的方法(例如区分分钟,然后划分为获得天数)

案例将取第一个正确的结果。按照您的方式,您永远不会到达 StatusDate4 或 GetDate,因为 StatusDate2 在前两个测试之一(NOT NULL 或 NULL)中总是 return。

您可以使用以下方法简化案例陈述:

CASE
    WHEN StatusDate2 IS NOT NULL THEN StatusDate2
    WHEN StatusDate3 IS NOT NULL THEN StatusDate3
    WHEN StatusDate4 IS NOT NULL THEN StatusDate4
    ELSE GETDATE()
END