从一个 table 中的多个日期时间列中查找最早的非 NULL 日期时间
Find earliest non-NULL datetime from several datetime columns in one table
我的数据库 (SQL Server 2012) 中有一个 table,它包含多个日期时间字段。假设所有字段都可以为空。我试图找到每行存在的最早的非 NULL 日期。
我尝试的解决方案是使用可怕的 CASE 表达式:
--To return the earliest non-NULL time that exists from table tmp
--Datetime fields are dt_lab_instrument, dt_lab_scan, dt_arrived, dt_receipted
SELECT
CASE
WHEN tmp.dt_lab_instrument IS NOT NULL AND tmp.dt_lab_instrument <= tmp.dt_lab_scan AND tmp.dt_lab_instrument <= tmp.dt_arrived AND tmp.dt_lab_instrument <= tmp.dt_receipted THEN tmp.dt_lab_instrument
WHEN tmp.dt_lab_scan IS NOT NULL AND tmp.dt_lab_scan <= tmp.dt_lab_instrument AND tmp.dt_lab_scan <= tmp.dt_arrived AND tmp.dt_lab_scan <= tmp.dt_receipted THEN tmp.dt_lab_scan
WHEN tmp.dt_arrived IS NOT NULL AND tmp.dt_arrived <= tmp.dt_lab_instrument AND tmp.dt_arrived <= tmp.dt_lab_scan AND tmp.dt_arrived <= tmp.dt_receipted THEN tmp.dt_arrived
WHEN tmp.dt_receipted IS NOT NULL AND tmp.dt_receipted <= tmp.dt_lab_instrument AND tmp.dt_receipted <= tmp.dt_lab_scan AND tmp.dt_receipted <= tmp.dt_arrived THEN tmp.dt_receipted
ELSE '1990-01-01' --If all else fails return dummy date value
END
from tmp
这很丑陋,效率低下,不处理空值,难以扩展(即尝试添加更多日期字段!)而且看起来是错误的。但我似乎对如何更好地解决这个问题有心理障碍。
我知道我可以通过使用 ISNULL 函数将任何 NULL 日期时间值替换为遥远未来的日期来处理空值,但这似乎只会让丑陋的代码变得更加丑陋。
有人可以帮我更好更有效地解决这个问题吗?非常感谢
如果我没猜错,你想获得这 4 个字段中最早的一个
dt_lab_instrument
dt_lab_scan
dt_arrived
dt_receipted
因此,您可以使用 MIN() 函数获取此字段中的 select 所有最小值,然后 select 来自此字段的最小值
SELECT MIN(C)
FROM (VALUES
(SELECT MIN(dt_lab_instrument) from tmp where dt_lab_instrument is not null),
(SELECT MIN(dt_lab_scan) from tmp where dt_lab_instrument is not null),
(SELECT MIN(dt_arrived) from tmp where dt_lab_instrument is not null),
(SELECT MIN(dt_receipted) from tmp where dt_lab_instrument is not null)
AS v (C)
使用 VALUES()
运算符将日期列反透视为行,并 MIN()
查找最早的
select *
from tmp t
cross apply
(
select min(dt) as min_dt
from
(
values (dt_lab_instrument), (dt_lab_scan), (dt_arrived), (dt_receipted)
) m (dt)
) m
处理If all else fails return dummy date value
,可以使用
ISNULL(min(dt), '1990-01-01')
或
COALESCE(min(dt), '1990-01-01')
我的数据库 (SQL Server 2012) 中有一个 table,它包含多个日期时间字段。假设所有字段都可以为空。我试图找到每行存在的最早的非 NULL 日期。
我尝试的解决方案是使用可怕的 CASE 表达式:
--To return the earliest non-NULL time that exists from table tmp
--Datetime fields are dt_lab_instrument, dt_lab_scan, dt_arrived, dt_receipted
SELECT
CASE
WHEN tmp.dt_lab_instrument IS NOT NULL AND tmp.dt_lab_instrument <= tmp.dt_lab_scan AND tmp.dt_lab_instrument <= tmp.dt_arrived AND tmp.dt_lab_instrument <= tmp.dt_receipted THEN tmp.dt_lab_instrument
WHEN tmp.dt_lab_scan IS NOT NULL AND tmp.dt_lab_scan <= tmp.dt_lab_instrument AND tmp.dt_lab_scan <= tmp.dt_arrived AND tmp.dt_lab_scan <= tmp.dt_receipted THEN tmp.dt_lab_scan
WHEN tmp.dt_arrived IS NOT NULL AND tmp.dt_arrived <= tmp.dt_lab_instrument AND tmp.dt_arrived <= tmp.dt_lab_scan AND tmp.dt_arrived <= tmp.dt_receipted THEN tmp.dt_arrived
WHEN tmp.dt_receipted IS NOT NULL AND tmp.dt_receipted <= tmp.dt_lab_instrument AND tmp.dt_receipted <= tmp.dt_lab_scan AND tmp.dt_receipted <= tmp.dt_arrived THEN tmp.dt_receipted
ELSE '1990-01-01' --If all else fails return dummy date value
END
from tmp
这很丑陋,效率低下,不处理空值,难以扩展(即尝试添加更多日期字段!)而且看起来是错误的。但我似乎对如何更好地解决这个问题有心理障碍。
我知道我可以通过使用 ISNULL 函数将任何 NULL 日期时间值替换为遥远未来的日期来处理空值,但这似乎只会让丑陋的代码变得更加丑陋。
有人可以帮我更好更有效地解决这个问题吗?非常感谢
如果我没猜错,你想获得这 4 个字段中最早的一个
dt_lab_instrument
dt_lab_scan
dt_arrived
dt_receipted
因此,您可以使用 MIN() 函数获取此字段中的 select 所有最小值,然后 select 来自此字段的最小值
SELECT MIN(C)
FROM (VALUES
(SELECT MIN(dt_lab_instrument) from tmp where dt_lab_instrument is not null),
(SELECT MIN(dt_lab_scan) from tmp where dt_lab_instrument is not null),
(SELECT MIN(dt_arrived) from tmp where dt_lab_instrument is not null),
(SELECT MIN(dt_receipted) from tmp where dt_lab_instrument is not null)
AS v (C)
使用 VALUES()
运算符将日期列反透视为行,并 MIN()
查找最早的
select *
from tmp t
cross apply
(
select min(dt) as min_dt
from
(
values (dt_lab_instrument), (dt_lab_scan), (dt_arrived), (dt_receipted)
) m (dt)
) m
处理If all else fails return dummy date value
,可以使用
ISNULL(min(dt), '1990-01-01')
或
COALESCE(min(dt), '1990-01-01')