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

时间:2014-04-01 01:13:01

标签: sql

    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

我一直试图弄清楚如何写这个查询好几天了,但还没有成功。我已经尝试过案例,(NULLIF(MAX(COALESCE(,max,子查询和其他几个,但无法弄清楚如何返回我需要的结果。

我需要查询要做的是根据到期日期和培训日期为每个培训ID返回1行。换句话说,查询需要首先查看expirationdate列,如果值为null,则检索最后一个traindate。如果expirationdate不为null,则返回最后的expirationdate。在上面的例子中,我需要结果:

    personsID          traindate          expirationdate     trainingID
    --------------------------------------------------------------------
    1                  2/1/2014           null               3
    1                  5/1/2014           5/30/2014          4

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

如果我的假设(请参阅问题评论)是正确的,那么这将在SQL Server中执行。

编辑:OP澄清是需要的。我已经以两种不同的方式包含了他想要的结果,但我认为我更喜欢选项2。

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

ORIGINAL:

棘手的部分是使用CASE WHEN EXISTS来处理NULL到期日期。除此之外,它看起来像是

的问题
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