SQL-检查第1列中的日期,如果为空,则将第2列中的日期与另一行进行比较,以返回更晚的日期

SQL-检查第1列中的日期,如果为空,则将第2列中的日期与另一行进行比较,以返回更晚的日期,sql,Sql,几天来,我一直在想如何编写这个查询,但都没有成功。我已经尝试过case,(NULLIF(MAX)(COALESCE(,MAX,subquerys)和其他一些方法,但无法找到如何返回所需的结果 我需要查询做的是根据Expiration date,然后是training date,为每个培训id返回1行。换句话说,查询需要首先查看expirationdate列,如果该值为null,则检索最后一个traindate。如果expirationdate不为null,则返回最后一个expirationdat

几天来,我一直在想如何编写这个查询,但都没有成功。我已经尝试过case,(NULLIF(MAX)(COALESCE(,MAX,subquerys)和其他一些方法,但无法找到如何返回所需的结果

我需要查询做的是根据Expiration date,然后是training date,为每个培训id返回1行。换句话说,查询需要首先查看expirationdate列,如果该值为null,则检索最后一个traindate。如果expirationdate不为null,则返回最后一个expirationdate。在上面的示例中ould需要的结果是:

    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