【问题标题】:Display accurate timing显示准确的时间
【发布时间】:2025-12-31 04:35:06
【问题描述】:

我有以下问题

SELECT
    CASE 
        WHEN CS.StartTime > CURRENT_TIMESTAMP THEN 'STARTING LATER'
        WHEN x.timing <  30 THEN 'A LITTLE LATE' 
        WHEN x.timing >= 30 THEN 'VERY LATE'
        ELSE 'Unknown Status'
    END as RefreshStartStatus,
    CASE WHEN CS.StartTime <= CURRENT_TIMESTAMP THEN CONCAT(x.timing ', min(s) late') END as info
FROM #CSTempTable CS
LEFT OUTER JOIN #SubscriptionAggTempTable SA ON SA.SubscriptionID = CS.SubscriptionID
CROSS APPLY (VALUES (DATEDIFF(MINUTE, CS.StartTime, SA.TodayFirstRunTime))) as x(timing)

示例结果:

RefreshStartStatus  info
A LITTLE LATE       0 min(s) late
STARTING LATER      NULL
A LITTLE LATE       9 min(s) late
A LITTLE LATE       0 min(s) late
STARTING LATER      NULL
A LITTLE LATE       0 min(s) late
VERY LATE           46 min(s) late
Unknown Status      min(s) late
A LITTLE LATE       0 min(s) late

这很好,但 0 有点误导。可能是毫秒级的差异导致刷新有点晚,那么我怎样才能让这个显示准确的时间呢?

例如

A LITTLE LATE       2 sec(s) late
A LITTLE LATE       1 min(s) late

或者如果这很复杂,那么

A LITTLE LATE       0.03 min(s) late
A LITTLE LATE       1 min(s) late

注意:2 秒等于 0.0333 分钟

【问题讨论】:

  • 您是否考虑过使用datetime2(0) 而不是datetime?或者,如果您只希望它精确到一分钟,那么smalldatetime

标签: sql sql-server string tsql lateral-join


【解决方案1】:

您可以将其用于低于 60 秒的顺从和高于 60 秒的顺从

 SELECT
CASE 
    WHEN CS.StartTime > CURRENT_TIMESTAMP THEN 'STARTING LATER'
    WHEN x.timing <  1800*1000 THEN 'A LITTLE LATE' 
    WHEN x.timing >= 1800*1000 THEN 'VERY LATE'
    ELSE 'Unknown Status'
END as RefreshStartStatus,
CASE WHEN CS.StartTime <= CURRENT_TIMESTAMP THEN 
    CASE WHEN x.timing < 1000 THEN
        CONCAT(x.timing ,', millisecond(s) late')
    WHEN x.timing < 60000 THEN
        CONCAT(x.timing/1000 ,', Second(s) late')
    ELSE
        CONCAT(x.timing/60000 ,', min(s) late')
    END
ELSE
CASE WHEN ABS(x.timing) < 1000 THEN
        CONCAT(ABS(x.timing) ,', millisecond(s) until it starts')
    WHEN ABS(x.timing) < 60000 THEN
        CONCAT(ABS(x.timing)/1000 ,', Second(s) until it starts')
    ELSE
        CONCAT(ABS(x.timing)/60000 ,', min(s) until it starts')
    END
END as info
FROM #CSTempTable CS
LEFT OUTER JOIN #SubscriptionAggTempTable SA ON SA.SubscriptionID = CS.SubscriptionID
CROSS APPLY (VALUES (DATEDIFF(MILLISECOND, CS.StartTime, SA.TodayFirstRunTime))) as x(timing)

我创建两个临时表并测试结果:

CREATE TABLE #CSTempTable
(
StartTime dateTime,
SubscriptionID int
)
CREATE TABLE #SubscriptionAggTempTable
(
SubscriptionID int,
TodayFirstRunTime datetime
)

并在表格中插入两行

 INSERT INTO #CSTempTable
VALUES (DATEADD(SECOND,-10,GETDATE()),1)

INSERT INTO #CSTempTable
VALUES (DATEADD(SECOND,10,GETDATE()),1)

INSERT INTO #CSTempTable
VALUES (DATEADD(MILLISECOND,-150,GETDATE()),1)

INSERT INTO #CSTempTable
VALUES (DATEADD(SECOND,-170,GETDATE()),1)

INSERT INTO #SubscriptionAggTempTable
VALUES (1,GETDATE())

运行后查询结果为:

【讨论】:

  • 哦,这太棒了!如果是毫秒呢?例如,0.4 秒
  • 我也将结果更改为毫秒
  • 太棒了!还有一件事,对于“稍后开始”,它在 Info 中显示 NULL,这是预期的……但我们可以改为显示多少分钟/秒/毫秒,直到它开始?我考虑过另一个像这样的 VALUES() 语句:CROSS APPLY (VALUES (DATEDIFF(SECOND, CS.StartTime, CURRENT_TIMESTAMP))) as x2(timing2) 但不确定这是否是正确的方法
  • 我也更改了结果以供稍后开始
  • 谢谢!这太棒了。存在未知状态,它在信息列中显示“开始之前的分钟数”。如果状态为未知,我想显示 NULL 或将其留空。我试过包括这个声明:AND RefreshStartStatus != 'Unknown Status',但是,我收到以下错误:Invalid column name RefreshStartStatus
【解决方案2】:

然后计算以秒为单位的差异,然后进行数学运算:

SELECT
    CASE 
        WHEN CS.StartTime > CURRENT_TIMESTAMP THEN 'STARTING LATER'
        WHEN x.timing <  30 * 60 THEN 'A LITTLE LATE' 
        WHEN x.timing >= 30 * 60 THEN 'VERY LATE'
        ELSE 'Unknown Status'
    END as RefreshStartStatus,
    CASE WHEN CS.StartTime <= CURRENT_TIMESTAMP THEN CONCAT(x.timing / 60.0,  ' min(s) late') END as info
FROM #CSTempTable CS
LEFT OUTER JOIN #SubscriptionAggTempTable SA ON SA.SubscriptionID = CS.SubscriptionID
CROSS APPLY (VALUES (DATEDIFF(SECOND, CS.StartTime, SA.TodayFirstRunTime))) as x(timing)

您可能希望格式化、舍入或截断除法的结果,以防它不能给出精确的结果,例如:

CONCAT(CONVERT(DECIMAL(10, 2), x.timing / 60.0),  ' min(s) late')

或者,如果您想仅显示有效的十进制数字,请使用FORMAT()

CONCAT(FORMAT(x.timing / 60.0, '0.##'),  ' min(s) late')

【讨论】:

  • @Cataster:然后使用FORMAT():查看我的更新。
  • 太棒了,太棒了!!顺便说一句,我们可以对未知状态做些什么吗?而不是显示“min(s) late”,而是显示 NULL 或 ???
  • @Cataster:类似于:CASE WHEN CS.StartTime &lt;= CURRENT_TIMESTAMP AND x.timing IS NOT NULL THEN ...