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
我有一个 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