【问题标题】:Check nullable date values for correct order检查可空日期值的正确顺序
【发布时间】:2014-08-11 22:38:42
【问题描述】:

我有一个包含日期的数据集,想检查日期顺序是否正确。

RecordID   Date1        Date2        Date3        Date4
1          2011-05-10   2011-08-16   NULL         2011-11-22
2          NULL         2012-02-03   2012-02-27   2012-03-05
3          2011-05-30   2011-05-11   2011-08-17   2011-09-15
4          2011-05-30   NULL         NULL         NULL

在提供日期的所有情况下,这应该满足:Date1

RecordID   Date1        Date2        Date3        Date4        CheckDates
1          2011-05-10   2011-08-16   NULL         2011-11-22   correct
2          NULL         2012-02-03   2012-02-27   2012-03-05   correct
3          2011-05-30   2011-05-11   2011-08-17   2011-09-15   incorrect
4          2011-05-30   NULL         NULL         NULL         correct

我为此写了一个广泛的 CASE 语句,但必须有一个更优雅的解决方案:

CASE
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NULL AND Date4 IS NULL THEN 'correct'
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NULL AND Date4 IS NOT NULL THEN 'correct'
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NOT NULL AND Date4 IS NULL THEN 'correct'
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NOT NULL AND Date4 IS NOT NULL AND Date3 < Date4 THEN 'correct'
  ...
  ELSE 'incorrect'
END

有什么想法吗?

编辑:
我正在寻找一种解决方案,它允许比我上面给出的第一个示例中的三列更多的“日期”列(我在现实世界的问题中有四个,并将其更改为三个以简化问题,但似乎通过这种简化,我失去了一个重要的特征)。更新了四列的示例。

【问题讨论】:

  • 您只是需要将值约束到此规则,还是需要获得行的“正确/不正确”结果?
  • 这是对现有数据的“正确/错误”检查。
  • 那么,你需要每行返回其中的数据是否符合规则?

标签: sql sql-server-2008 tsql


【解决方案1】:

您可以使用ISNULLCOALESCE 跳过空值。如果缺少日期,只需将其替换为始终通过检查的日期即可:

CASE
  WHEN (ISNULL(Date1, '01/01/1900') < COALESCE(Date2, Date3, Date4, '01/01/3000'))
   AND (ISNULL(Date2, '01/01/1900') < COALESCE(Date3, Date4, '01/01/3000'))
   AND (ISNULL(Date3, '01/01/1900') < COALESCE(Date4, '01/01/3000'))
  THEN 'correct'
  ELSE 'incorrect'
END

这假设您的“真实”日期当然永​​远不会超出 1900 - 3000 的范围;下一个千年虫正等着发生;)

编辑:编辑处理四个字段

【讨论】:

  • 对于这个包含三列的示例来说,这将是一个很好的解决方案,谢谢。我正在寻找在有更多列时也可以使用的东西。
  • @Josien:针对 4 个字段进行了编辑。主要的是,表达式线性增长,而不是原始版本需要检查空字段的所有组合——这将呈指数增长。如果您正在寻找可以使用可变数量字段的东西,那通常超出“正常” SQL 的范围,并诉诸某种字符串构建和 EXEC。
  • 简洁的解决方案,就像一个魅力!我会冒险应对千年虫风险:-)
【解决方案2】:

您可以在比较日期的选择中使用大小写,并使用 ISNULL 函数,如果第一个参数不为空,则返回第二个参数。

在这种情况下,我将开始日期设置为早期日期,结束日期设置为旧日期

select date1,date2,date3,
     case
        when isnull(date1,'01/01/1900') <isnull(date2,'01/01/2100') and isnull(date2,'01/01/1900') <isnull(date3,'2100') then 'OK'
        else 'not OK'
    end
from testDates

【讨论】:

  • 对于这个包含三列的示例来说,这将是一个很好的解决方案,谢谢。我正在寻找在有更多列时也可以使用的东西。
  • @Diego:这个解决方案不起作用。假设 date1 是 1950,date2 是 null,date3 是 1949。表达式将返回 true,但日期的顺序不正确。在进行比较时,您需要使用 coalesce 跳过空值。
【解决方案3】:

这是另一种方法:

WITH data (
  RecordID,  Date1      , Date2      , Date3      , Date4
) AS (
  SELECT 1, '2011-05-10','2011-08-16', NULL       ,'2011-11-22' UNION ALL
  SELECT 2,  NULL       ,'2012-02-03','2012-02-27','2012-03-05' UNION ALL
  SELECT 3, '2011-05-30','2011-05-11','2011-08-17','2011-09-15' UNION ALL
  SELECT 4, '2011-05-30', NULL       , NULL       , NULL
)
SELECT
  *,
  CheckDates = (
    SELECT
      MAX(CASE IdRank WHEN DateRank THEN 'correct' ELSE 'incorrect' END)
    FROM (
      SELECT
        IdRank   = ROW_NUMBER() OVER (ORDER BY ID),
        DateRank = ROW_NUMBER() OVER (ORDER BY Date)
      FROM (
        VALUES
          (1, Date1),
          (2, Date2),
          (3, Date3),
          (4, Date4)
      ) s (ID, Date)
      WHERE Date IS NOT NULL
    ) s
  )
FROM data

这是输出:

RecordID    Date1      Date2      Date3      Date4      CheckDates
----------- ---------- ---------- ---------- ---------- ----------
1           2011-05-10 2011-08-16 NULL       2011-11-22 correct
2           NULL       2012-02-03 2012-02-27 2012-03-05 correct
3           2011-05-30 2011-05-11 2011-08-17 2011-09-15 incorrect
4           2011-05-30 NULL       NULL       NULL       correct

检查表达式比 @njr's answer 中的更复杂,但是,我想,当您需要扩展脚本以支持更多列时,它会有所回报:您只需要在 @987654324 之后添加新行@ 子句。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多