SQL 查询 return 基于多个日期列的最新记录更新(棘手?)

SQL query to return most recent record update based on multiple date columns (tricky?)

我有一个 table 可以跟踪一组设备完成的各个阶段的日期。我需要确定最近更新的设备(即具有最新日期戳的设备),无论哪个阶段更新以及 return 设备 ID、更新日期和阶段。容易,对吧?好吧,这比听起来有点棘手。这里有一个问题:每个阶段都表示为 table 中的不同字段,并且重新设计 table 结构不是一个选项(事务性 table 会让这变得很简单。)这是table 结构是什么样的。

equip_id (text)
stage_1_process (date)
stage_2_process (date)
stage_3_process (date)
stage_4_process (date)
stage_5_process (date)

如果该字段包含日期,则认为该阶段已完成;如果该字段为空,则该阶段被视为未完成。

使用 Max() 函数的联合查询可以获得最近的日期:

SELECT Max(dt) AS latest 
FROM (
    SELECT Max(stage_1_process) AS dt, 'Stage 1' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_2_process) AS dt, 'Stage 2' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_3_process) AS dt, 'Stage 3' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_4_process) AS dt, 'Stage 4' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_5_process) AS dt, 'Stage 5' as stage
    FROM equip_status) AS U;

添加了 'stage' 别名以捕获最新日期与哪个阶段相关联。但是,我不知道如何在顶级查询中 return 也不知道如何捕获 equip_id,因为它不能从聚合函数派生。

这是我需要的结果集示例 return:

equip_id | stage   | latest
--------------------------------------------
A12345   | Stage 3 | 4/21/2016 3:56:39 PM

感谢您的帮助!

您可以使用 post 的查询作为派生的 table:

加入
SELECT t1.equip_id, 
       t2.lastest,
       CASE t2.latest
          WHEN t1.stage_1_process THEN 'Stage 1'
          WHEN t1.stage_2_process THEN 'Stage 2'
          WHEN t1.stage_3_process THEN 'Stage 3'
          WHEN t1.stage_4_process THEN 'Stage 4'
          WHEN t1.stage_5_process THEN 'Stage 5'
       END AS stage
FROM equip_status AS t1
JOIN (
  SELECT Max(dt) AS latest 
  FROM (
    SELECT Max(stage_1_process) AS dt, 'Stage 1' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_2_process) AS dt, 'Stage 2' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_3_process) AS dt, 'Stage 3' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_4_process) AS dt, 'Stage 4' as stage
    FROM equip_status
    UNION
    SELECT Max(stage_5_process) AS dt, 'Stage 5' as stage
    FROM equip_status) AS U
) AS t2 ON t2.latest IN (t1.stage_1_process, 
                         t1.stage_2_process,
                         t1.stage_3_process,
                         t1.stage_4_process,
                         t1.stage_5_process)

这看起来很丑陋,但这些是未正确规范化 table 结构的结果。

一种方法是实现一个函数,returns给定行的 5 个阶段的最大阶段的值:

From http://allenbrowne.com/func-09.html

Function MaxOfList(ParamArray varValues()) As Variant
  Dim i As Integer        'Loop controller.
  Dim varMax As Variant   'Largest value found so far.

  varMax = Null           'Initialize to null

  For i = LBound(varValues) To UBound(varValues)
      If IsNumeric(varValues(i)) Or IsDate(varValues(i)) Then
          If varMax >= varValues(i) Then
              'do nothing
          Else
              varMax = varValues(i)
          End If
        End If
  Next

  MaxOfList = varMax 
End Function

现在您可以将 case 语句与 MaxOfList

一起使用
select top 1 
    equip_id,
    latest,
    case when stage_1_process = latest then 'stage 1'
    when stage_2_process = latest then 'stage 2'
    when stage_3_process = latest then 'stage 3'
    when stage_4_process = latest then 'stage 4'
    when stage_5_process = latest then 'stage 5'
    else 'none' end
 from (
    select *, 
        MaxOfList(stage_1_process,stage_2_process,stage_3_process,
                stage_4_process,stage_5_process) as latest
    from equip_status
) t order by latest desc