【问题标题】:MAX Date of multiple columns?多列的最大日期?
【发布时间】:2014-06-04 23:10:57
【问题描述】:

如何在多列的最大值中每行返回 1 个值:

TableName [RefNumber, FirstVisitedDate, SecondVisitedDate, RecoveryDate, ActionDate]

我希望 MaxDate of (FirstVisitedDate, SecondVisitedDate, RecoveryDate, ActionDate) 这些日期用于单列中的所有行,并且我想要另一个新列 (Acion) 取决于 Max date 列,例如:如果 Max date 来自 FirstVisitedDate 那么它将是“FirstVisited”,或者如果 Max 日期来自 SecondVisitedDate,那么它将是“SecondVisited”...

总的结果喜欢:

从表中选择 RefNumber、Maxdate、Action 按 RefNumber 分组

【问题讨论】:

    标签: sql sql-server sql-server-2008 tsql reporting


    【解决方案1】:

    四列的蛮力方法还不错:

    select (case when FirstVisitedDate >= SecondVisitedDate and
                      FirstVisitedDate >= RecoveryDate and
                      FirstVisitedDate >= ActionDate
                 then FirstVisitedDate
                 when SecondVisitedDate >= RecoveryDate and
                      SecondVisitedDate >= ActionDate
                 then SecondVisitedDate 
                 when RecoveryDate >= ActionDate
                 then RecoveryDate
                 else ActionDate
            end),
           (case when FirstVisitedDate >= SecondVisitedDate and
                      FirstVisitedDate >= RecoveryDate and
                      FirstVisitedDate >= ActionDate
                 then 'FirstVisitedDate'
                 when SecondVisitedDate >= RecoveryDate and
                      SecondVisitedDate >= ActionDate
                 then 'SecondVisitedDate'
                 when RecoveryDate >= ActionDate
                 then 'RecoveryDate'
                 else 'ActionDate'
            end)     
    from table t;
    

    编辑:

    group by 中这样做只是添加聚合函数的问题:

    select RefNumber,
           (case when max(FirstVisitedDate) >= max(SecondVisitedDate) and
                      max(FirstVisitedDate) >= max(RecoveryDate) and
                      max(FirstVisitedDate) >= max(ActionDate)
                 then max(FirstVisitedDate
                 when max(SecondVisitedDate) >= max(RecoveryDate) and
                      max(SecondVisitedDate) >= max(ActionDate)
                 then max(SecondVisitedDate) 
                 when max(RecoveryDate) >= max(ActionDate)
                 then max(RecoveryDate)
                 else max(ActionDate)
            end),
           (case when max(FirstVisitedDate) >= max(SecondVisitedDate) and
                      max(FirstVisitedDate) >= max(RecoveryDate) and
                      max(FirstVisitedDate) >= max(ActionDate)
                 then 'FirstVisitedDate'
                 when max(SecondVisitedDate) >= max(RecoveryDate) and
                      max(SecondVisitedDate) >= max(ActionDate)
                 then 'SecondVisitedDate'
                 when max(RecoveryDate) >= max(ActionDate)
                 then 'RecoveryDate'
                 else 'ActionDate'
            end)     
    from table t
    group by RefNumber;
    

    【讨论】:

    • 嗨戈登林诺夫,感谢您的回复。但是我有 9 个日期列来获取 Maxdate ..以上仅用于示例..谢谢
    • @user3583912 。 . .九列的逻辑并不难,只是大量的复制和粘贴。但它确实强调了greatest()least() 函数在其他数据库中的用处。
    • 我会这样做的..是的,你的权利这些是 Mysql 中有用的功能
    【解决方案2】:
    ;WITH cte AS (
      -- Build table of date 
      SELECT [RefNumber], 
             [ActionDate]= [FirstVisitedDate], 
             [Action] = 'First Visited' 
      FROM [Table1] 
      UNION ALL
      SELECT [RefNumber], 
             [SecondVisitedDate],  
             'Second Visited' 
      FROM [Table1] 
      UNION ALL
      SELECT [RefNumber], 
             [RecoveryDate], 
             'Recover'
      FROM [Table1]
    ), cte2 AS (
      -- Add row_number to pull most recent to top
      SELECT  [RefNumber],
              [Action],
              [ActionDate],
              [DateRank] = 
                  ROW_NUMBER() OVER (PARTITION BY RefNumber 
                                     ORDER BY [ActionDate] DESC)
      FROM [cte]
    )
    -- select only the most recent
    SELECT * 
    FROM cte2 
    WHERE [DateRank] = 1
    

    【讨论】:

      【解决方案3】:
      SELECT RecordID, MaxDate
      FROM SourceTable
          CROSS APPLY (SELECT MAX(d) MaxDate 
                      FROM (VALUES (date1), (date2), (date3), 
                                   (date4), (date5), (date6), 
                                   (date7)) AS dates(d)) md
      

      【讨论】:

      • 这太棒了——在一些不同的事情上使用了 CROSS APPLY,但之前从未见过带有 Values 的语法,在进行 5 多个 mod 日期查找时对我非常有用。但是,它并没有解决 Q 中指定的返回操作,尽管对于人们 ref,这自 2008 年以来一直存在于 sql 中
      【解决方案4】:

      我为此编写了一个自定义函数:

      CREATE FUNCTION [dbo].[MaxOf5]
      (
          @D1 DateTime,
          @D2 DateTime,
          @D3 DateTime,
          @D4 DateTime,
          @D5 DateTime
      )
      RETURNS DateTime
      AS
      BEGIN
          DECLARE @Result DateTime
      
          SET @Result = COALESCE(@D1, @D2, @D3, @D4, @D5)
      
          IF @D2 IS NOT NULL AND @D2 > @Result SET @Result = @D2
          IF @D3 IS NOT NULL AND @D3 > @Result SET @Result = @D3
          IF @D4 IS NOT NULL AND @D4 > @Result SET @Result = @D4
          IF @D5 IS NOT NULL AND @D5 > @Result SET @Result = @D5
      
          RETURN @Result
      END
      

      要调用它并计算您的 Action 列,这应该可以工作:

      SELECT
          MaxDate,
          CASE WHEN MaxDate = FirstVisitedDate THEN 'FirstVisited'
             WHEN MaxDate = SecondVisitedDate THEN 'SecondVisited'
             WHEN MaxDate = RecoveryDate THEN 'Recovery'
             WHEN MaxDate = ActionDate THEN 'Action'
          END AS [Action]
      FROM (
          SELECT
             RefNumber,
             dbo.MaxOf5(FirstVisitedDate, SecondVisitedDate, RecoveryDate, ActionDate) AS MaxDate,
             FirstVisitedDate, SecondVisitedDate, RecoveryDate, ActionDate
          FROM table
      ) AS data
      

      请注意,您可以将多个日期与最大日期绑定。在这种情况下,WHEN 子句的顺序决定了哪一个获胜。

      【讨论】:

      • 嗨大卫,感谢您的回复..您的代码一切正常,但我无法按 RefNumber 进行分组..请您检查一次..谢谢
      • @user3583912,如果有 2 行具有相同的RefNumber,您如何选择返回的日期和操作?
      猜你喜欢
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多