【问题标题】:Selecting most recent date between two columns在两列之间选择最近的日期
【发布时间】:2009-01-05 19:33:00
【问题描述】:

如果我有一个表(在其他列中)有两个 DATETIME 列,我将如何从这两列中选择最近的日期。

例子:

ID     Date1     Date2

1      1/1/2008   2/1/2008

2      2/1/2008   1/1/2008

3      1/10/2008  1/10/2008

如果我希望我的结果看起来像

ID     MostRecentDate

1      2/1/2008

2      2/1/2008

3      1/10/2008

有没有一种我显然忽略的简单方法?我知道我可以做子查询和 case 语句,甚至可以在 sql server 中编写一个函数来处理它,但我脑子里有一个已经内置的 max-compare 类型函数,我只是忘记了。

【问题讨论】:

    标签: sql database sql-server-2005


    【解决方案1】:

    CASE 恕我直言是您的最佳选择:

    SELECT ID,
           CASE WHEN Date1 > Date2 THEN Date1
                ELSE Date2
           END AS MostRecentDate
    FROM Table
    

    如果其中一列可以为空,只需将COALESCE括起来:

    .. COALESCE(Date1, '1/1/1973') > COALESCE(Date2, '1/1/1973')
    

    【讨论】:

    • 我认为是这样。我几乎可以肯定已经建立了一个日期比较函数,我可以说“选择 ID,max(date1, date2)”。
    • 我们可以给出空白字符串 '' 而不是给出一个日期,例如 '1/1/1973',它应该根据使用的日期类型转换为最早的日期。例如CAST('' as date) 返回“1900-01-01”,CAST('' as datetime) 返回“1900-01-01 00:00:00.000”,CAST('' as datetime2) 返回“1900-01- 01 00:00:00.0000000”。这适用于 SQL Server 2019。
    【解决方案2】:

    SQL Server 2012 可以使用快捷方式 IIFCASE 表达式,尽管后者是 SQL 标准:

    SELECT ID,
           IIF(DateColA > DateColB, DateColA, DateColB) AS MostRecentDate
      FROM theTable
    

    【讨论】:

      【解决方案3】:
      select ID, 
      case
      when Date1 > Date2 then Date1
      else Date2
      end as MostRecentDate
      from MyTable
      

      【讨论】:

      • 看来我们达成了共识:)
      【解决方案4】:

      您可以将它放入一个标量函数中,这样可以更轻松地处理空值。显然它不会比内联 case 语句快。

      ALTER FUNCTION [fnGetMaxDateTime] (
          @dtDate1        DATETIME,
          @dtDate2        DATETIME
      ) RETURNS DATETIME AS
      BEGIN
          DECLARE @dtReturn DATETIME;
      
          -- If either are NULL, then return NULL as cannot be determined.
          IF (@dtDate1 IS NULL) OR (@dtDate2 IS NULL)
              SET @dtReturn = NULL;
      
          IF (@dtDate1 > @dtDate2)
              SET @dtReturn = @dtDate1;
          ELSE
              SET @dtReturn = @dtDate2;
      
          RETURN @dtReturn;
      END
      

      【讨论】:

        【解决方案5】:

        我认为公认的答案是最简单的。但是,我会注意日期中的空值...

        SELECT ID,
               CASE WHEN ISNULL(Date1,'01-01-1753') > ISNULL(Date2,'01-01-1753') THEN Date1
                    ELSE Date2
               END AS MostRecentDate
        FROM Table
        

        【讨论】:

          【解决方案6】:

          除了case语句,我不这么认为……

            Select Case When DateColA > DateColB Then DateColA 
                        Else DateColB End MostRecent
            From Table ... 
          

          【讨论】:

            【解决方案7】:

            尽可能使用内联函数,因为它们不会遇到通常与 UDF 相关的性能问题...

            Create FUNCTION MaximumDate 
            (   
            @DateTime1 DateTime,
            @DateTime2 DateTime
            )
            RETURNS TABLE 
            AS
            RETURN 
            (
                Select Case When @DateTime1 > @DateTime2 Then @DateTime1
                            Else @DateTime2 End MaxDate
            )
            GO 
            

            有关使用指南,请参阅Here

            【讨论】:

              【解决方案8】:

              AFAIK,没有内置函数可以获取两个值的最大值,但您可以轻松编写自己的函数:

              CREATE FUNCTION dbo.GetMaximumDate(@date1 DATETIME, @date2 DATETIME)
              RETURNS DATETIME
              AS
              BEGIN
                  IF (@date1 > @date2)
                      RETURN @date1
                  RETURN @date2
              END
              

              并将其称为

              SELECT Id, dbo.GetMaximumDate(Date1, Date2)
              FROM tableName
              

              【讨论】:

              • 这实际上是我最终要为将来使用而做的事情。由于它的简单性,我在这个特定问题上使用了 case 方法,但最大日期函数是我应该拥有的
              • 这是最好的答案。
              【解决方案9】:

              为什么不能使用 GREATEST 功能?

              select id, date1, date2, GREATEST( nvl(date1,date2) , nvl(date2, date1) )
              from table1;
              

              我包含一个 NVL 以确保正确评估 NULL,否则如果 Date1 或 Date2 为 null,则 Greatest 返回 NULL。

              ID  Date1       Date2       MostRecentDate
              1   1/1/2008    2/1/2008    2/1/2008
              2   2/1/2008    1/1/2008    2/1/2008
              3   1/10/2008   1/10/2008   1/10/2008
              4   -null-      2/10/2008   2/10/2008
              5   2/10/2008   -null-      2/10/2008
              

              【讨论】:

              • 问题是关于 SQL-Server 而不是 Oracle。
              【解决方案10】:

              已发布的所有其他正确答案。

              但是,如果您仍然真的在寻找 MAX 关键字,那么这里有一个方法:

              select ID , MAX(dt) from 
              (  select Id , Date1 as dt from table1
                 union  
                 select ID , Date2 from table2
              ) d
              group by d.Id
              

              【讨论】:

                【解决方案11】:

                This thread 有几种解决方案。如果您有超过 2 个日期要比较,“unpivot”可能比编写一系列案例陈述更可取。以下内容公然盗用Niikola

                select id, max(dDate) MostRecentDate
                  from YourTable
                    unpivot (dDate for nDate in (Date1, Date2, Date3)) as u
                  group by id 
                

                那你可以order by dDate,如果有帮助的话。

                【讨论】:

                  【解决方案12】:
                  select max(d) ChangeDate
                  from (values(@d), (@d2)) as t(d)
                  

                  【讨论】:

                    【解决方案13】:
                    select ID,(select max(d) from (select Date1 d uninon select Date2 d) as t) as MaxDate
                    from MyTable
                    

                    【讨论】:

                    • 虽然这个答案可能是正确的。仅代码答案很少有帮助。请评论您的代码并解释此代码如何解决问题。
                    猜你喜欢
                    • 2014-02-24
                    • 2021-09-14
                    • 2011-11-03
                    • 1970-01-01
                    • 2014-09-17
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-11-23
                    相关资源
                    最近更新 更多