SQL-检查第1列中的日期,如果为空,则将第2列中的日期与另一行进行比较,以返回更晚的日期
几天来,我一直在想如何编写这个查询,但都没有成功。我已经尝试过case,(NULLIF(MAX)(COALESCE(,MAX,subquerys)和其他一些方法,但无法找到如何返回所需的结果 我需要查询做的是根据Expiration date,然后是training date,为每个培训id返回1行。换句话说,查询需要首先查看expirationdate列,如果该值为null,则检索最后一个traindate。如果expirationdate不为null,则返回最后一个expirationdate。在上面的示例中ould需要的结果是:SQL-检查第1列中的日期,如果为空,则将第2列中的日期与另一行进行比较,以返回更晚的日期,sql,Sql,几天来,我一直在想如何编写这个查询,但都没有成功。我已经尝试过case,(NULLIF(MAX)(COALESCE(,MAX,subquerys)和其他一些方法,但无法找到如何返回所需的结果 我需要查询做的是根据Expiration date,然后是training date,为每个培训id返回1行。换句话说,查询需要首先查看expirationdate列,如果该值为null,则检索最后一个traindate。如果expirationdate不为null,则返回最后一个expirationdat
personsID traindate expirationdate trainingID
-------------------------------------------------------------------
1 1/1/2014 null 3
1 2/1/2014 null 3
1 3/1/2014 4/1/2014 3
1 4/1/2014 4/30/2014 4
1 5/1/2014 5/30/2014 4
任何帮助都将不胜感激。如果我的假设(参见问题注释)是正确的,那么这将在SQL Server中实现
编辑:OP已经澄清了他的需要。我已经用两种不同的方式列出了他想要的结果,但我想我更喜欢选项2
personsID traindate expirationdate trainingID
--------------------------------------------------------------------
1 2/1/2014 null 3
1 5/1/2014 5/30/2014 4
原件:
棘手的部分是使用CASE WHEN EXISTS来处理空的过期日期。除此之外,它看起来是一个时间问题
DECLARE @tbl TABLE(personsID INT
,traindate DATE
,expirationdate DATE
,trainingID INT)
INSERT INTO @tbl VALUES
(1,'1/1/2014',null,3)
,(1,'2/1/2014',null,3)
,(1,'3/1/2014','4/1/2014',3)
,(1,'4/1/2014','4/30/2014',4)
,(1,'5/1/2014','5/30/2014',4)
SELECT personsID
,trainingID
,CASE WHEN EXISTS(SELECT 1
FROM @tbl a
WHERE a.personsID=b.personsID
AND a.trainingID =b.trainingID
AND a.expirationdate IS NULL)
THEN (SELECT MAX(traindate)
FROM @tbl a
WHERE a.personsID=b.personsID
AND a.trainingID =b.trainingID
AND a.expirationdate IS NULL )
ELSE MAX(traindate)
END maxtraindatethatdoesntexpire_option1
,(SELECT TOP 1
traindate
FROM @tbl a
WHERE a.personsID=b.personsID
AND a.trainingID =b.trainingID
ORDER BY CASE WHEN a.expirationdate IS NULL THEN 1 ELSE 0 END DESC
,traindate DESC
) maxtraindatethatdoesntexpire_option2
,CASE WHEN EXISTS(SELECT 1
FROM @tbl a
WHERE a.personsID=b.personsID
AND a.trainingID =b.trainingID
AND a.expirationdate IS NULL)
THEN NULL
ELSE MAX(expirationdate)
END expirationdate
FROM @tbl b
GROUP BY personsID,trainingID
什么数据库引擎?为什么是2个记录而不是一个?我不清楚逻辑。我希望从文本中可以看出,您希望1,3/1/2013,null,3作为示例中的第一行。这比我想象的要复杂。数据集中的行是否按所示顺序排列?Karl是正确的。2014年3月1日是id 3What DB engine:I am usi中的最后一列火车日期ng MS sql。我需要检索2条记录的原因是,它代表同一个人的2条培训记录。实际数据集中的顺序与显示的顺序不同。培训日期和过期日期可以是任意顺序。我需要记录1 2/1/2014 null 3而不是1 3/1/2014 4/1/2014 3是因为2/1/2014记录不正确2014年3月1日的记录将到期。我感谢您的帮助,但上面的内容没有完全起作用。它返回了培训记录4的正确记录(1、'5/1/2014'、'5/30/2014',4),但不适用于培训ID 3。它返回了带有2014年3月1日培训日期的行,但我需要它返回具有空过期日期的2014年2月1日行。这是永远不会过期的最新培训日期。感谢您的帮助。您可以想象,实际完成的查询比我在问题中询问的要复杂得多n、 但是,你给了我一个很好的开始-谢谢!!!很高兴能提供帮助。尝试发布一个简化版本来代表你已经做过的场景是很标准的,所以在你的第一个问题上做得很好。因为这很有用并且回答了你的问题,请投票并接受答案以结束循环。我将问题标记为已回答,t我很高兴能提高你的投票率,但我要传达的信息是,它“需要15%的声誉”,不会让我改变。你确实回答了我的问题,但我不知道现在该为你做些什么。有没有办法提高投票率?
DECLARE @tbl TABLE(personsID INT
,traindate DATE
,expirationdate DATE
,trainingID INT)
INSERT INTO @tbl VALUES
(1,'1/1/2014',null,3)
,(1,'2/1/2014',null,3)
,(1,'3/1/2014','4/1/2014',3)
,(1,'4/1/2014','4/30/2014',4)
,(1,'5/1/2014','5/30/2014',4)
SELECT personsID
,trainingID
,MAX(traindate) traindate
,CASE WHEN EXISTS(SELECT 1
FROM @tbl a
WHERE a.personsID=b.personsID
AND a.trainingID =b.trainingID
AND a.expirationdate IS NULL)
THEN NULL
ELSE MAX(expirationdate)
END expirationdate
FROM @tbl b
GROUP BY personsID,trainingID