[英]Check nullable date values for correct order
我有一个包含日期的数据集,想要检查日期顺序是否正确。
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 <Date2 <Date3 <Date4。 当记录包含某些日期的NULL值时,应检查非NULL的日期。 所以这就是我想要的结果:
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
有任何想法吗?
编辑:
我正在寻找一个解决方案,允许比上面给出的第一个例子中的三列更多“日期”列(我的实际问题中有四个,并将其更改为三个以简化问题,但似乎我已经失去了这种简化的重要特征)。 更新了四列的示例。
您可以使用ISNULL
和COALESCE
跳过空值。 如果缺少日期,只需将其替换为始终通过检查的日期:
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当然; 还有下一个等待发生的千年虫;)
编辑:编辑处理四个字段
您可以在select上比较日期时使用case,并使用ISNULL函数返回第一个参数(如果它不为null)或第二个参数(如果firs为null)。
在这种情况下,我将开始日期设置为早期日期,将结束日期设置为旧日期
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
这是另一种方法:
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的答案更复杂,但是,我想,当您需要扩展脚本以支持更多列时,它会得到回报:您只需要在VALUES
子句之后添加新行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.