【问题标题】:SQL: get DATEDIFF to not return negative valuesSQL:让 DATEDIFF 不返回负值
【发布时间】:2010-09-20 14:03:22
【问题描述】:

我有一个查询,我在其中提取可执行文件的运行时。数据库包含它的开始时间和结束时间。我想获得跑步的总时间。 到目前为止,我有:

SELECT startTime, endTime,
cast(datediff(hh,starttime,endtime) as varchar)
+':'
+cast(datediff(mi,starttime,endtime)-60*datediff(hh,starttime,endtime) as varchar) AS RUNTIME
FROM applog
WHERE runID = 33871
ORDER BY startTime DESC 

当我执行这个时,我得到了预期的值,也得到了一些意想不到的值。 例如,如果 starttime = 2008-11-02 15:59:59.790 和 endtime = 2008-11-02 19:05:41.857,则运行时间 = 4:-54。 在这种情况下,如何在 MS SQL SMS 中获取查询以返回值 3:06?

谢谢。

我选择的 Eoin Campbell 是最能满足我需求的。 David B 的也可以。

【问题讨论】:

    标签: sql sql-server-2005 tsql datediff


    【解决方案1】:

    Here's 一种方法:

    -- Find Hours, Minutes and Seconds in between two datetime
    DECLARE @First datetime
    DECLARE @Second datetime
    SET @First = '04/02/2008 05:23:22'
    SET @Second = getdate()
    
    SELECT DATEDIFF(day,@First,@Second)*24 as TotalHours,
    DATEDIFF(day,@First,@Second)*24*60 as TotalMinutes,
    DATEDIFF(day,@First,@Second)*24*60*60 as TotalSeconds
    

    【讨论】:

    • 如果您从日历日期的角度考虑,这非常有用,但所有这些答案都是“日大小”的块。 3:06 显然不是一天大小的块。
    【解决方案2】:

    您应该将计算和表示逻辑分开:

    DECLARE @applog TABLE
    (
      runID int,
      starttime datetime,
      endtime datetime
    )
    
    INSERT INTO @applog (runID, starttime, endtime)
    SELECT 33871, '2008-11-02 15:59:59.790', '2008-11-02 19:05:41.857'
    -------------------
    SELECT
      SUBSTRING(convert(varchar(30), DateAdd(mi, duration, 0), 121),
      12, 5) as prettyduration
    FROM
    (
    SELECT starttime, DateDiff(mi, starttime, endtime) as duration
    FROM @applog
    WHERE runID = 33871
    ) as sub
    

    如果您需要表示超过 24 小时,您将使用不同的表示逻辑。这只是我能想到的最快的。

    【讨论】:

      【解决方案3】:

      试试这些

      假设 2 个声明的日期。

      declare @start datetime
      set @start = '2008-11-02 15:59:59.790'
      
      declare @end datetime
      set @end = '2008-11-02 19:05:41.857'
      

      这将返回小时/分钟/秒

      select 
          (datediff(ss, @start, @end) / 3600), 
          (datediff(ss, @start, @end) / 60) % 60,
          (datediff(ss, @start, @end) % 60) % 60
      
      --returns
      
      ----------- ----------- -----------
      3           5           42
      

      这是零填充的串联字符串版本

      select
      RIGHT('0' + CONVERT(nvarchar, (datediff(ss, @start, @end) / 3600)), 2) + ':' +
      RIGHT('0' + CONVERT(nvarchar, (datediff(ss, @start, @end) / 60) % 60), 2) + ':' +
      RIGHT('0' + CONVERT(nvarchar, (datediff(ss, @start, @end) % 60) % 60), 2)
      
      --------
      03:05:42
      

      【讨论】:

      • 超级!正是我需要的!谢谢!
      • 我尝试了上面的代码来满足我的需求,但问题是我的开始时间大于结束时间。负值只出现几分钟。例如,假设开始时间是 07:31:01,结束时间是 07:30:03,结果是 00:00:58,他们说应该是 -58。我们能把它设为 00:00:-58 吗?
      • 我尝试了以下代码: CONVERT(NVARCHAR, (Dateiff(ss, raa.schedtime, raa.actualtime) / 3600), 2) + ':' + CONVERT(NVARCHAR, (Datediff(ss , raa.schedtime, raa.actualtime) / 60) % 60, 2) + ':' + CONVERT(NVARCHAR, (Dateiff(ss, raa.schedtime, raa.actualtime) % 60) % 60, 2) 这让我结果 0:0:-58 但如您所见,它不是 hh:mm:ss 格式
      【解决方案4】:

      您需要与对 datediff() 的调用保持一致。它们都应该使用相同的 datepart 参数。

      MSDN's DATEDIFF (Transact-SQL) article

      在您的示例中,您同时使用“mi”和“hh”并进行连接。

      为您的持续时间选择最小的公分母(可能是 ss 或 s)并基于此进行任何数学运算(正如其他答案所说明的,但不是真正描述的那样)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多