【问题标题】:Calculating timespan with t-sql使用 t-sql 计算时间跨度
【发布时间】:2009-04-17 03:24:14
【问题描述】:

给定两个日期/时间:

@start_date = '2009-04-15 10:24:00.000'
@end_date = '2009-04-16 19:43:01.000'

是否可以按以下格式计算两个日期之间经过的时间

1d 9h 19m

【问题讨论】:

    标签: sql-server-2005 tsql


    【解决方案1】:
    CONVERT(varchar,(@end_date-@start_date),108)
    

    这会将它作为 HH:MM:SS 提供给您

    干杯

    【讨论】:

    【解决方案2】:

    您可以get the difference between the two dates 达到您想要的任何分辨率(在您的示例中为分钟):

    DATEDIFF(minute, @start_date, @end_date)
    

    从那里开始,只需将分钟划分为小时,将小时划分为天,然后修改其余部分。

    【讨论】:

    • 我可以看到 DATEDIFF 是如何工作的,但它总是返回 TOTAL 时间。我可以获得总天数或总小时数,但我无法获得 1 天 9 小时的跨度。至少不是直接的方式。例子?
    • @jdiaz 如答案中所述,您需要以所需的精度获得总数。如果您需要精确到分钟,则以分钟为单位,然后除以 60 得到小时(余数是分钟),然后将小时除以 24 得到天数(余数是小时)。
    • 如果您使用 DATEDIFF(second, @start_date, @end_date),此示例 classicasp.aspfaq.com/date-time-routines-manipulation/… 将帮助您了解如何将秒转换为 HH:MM:SS。
    • @JJS 链接失效了。
    • 这应该可以解决问题: SELECT CAST(DATEDIFF(second, \@start_date, \@end_date) / 3600 AS varchar(max)) + ':' + RIGHT('0' + CAST( DATEDIFF(second, \@start_date, \@end_date) % 3600 / 60 AS varchar(2)), 2) + ':' + RIGHT('0' + CAST(DATEDIFF(second, \@start_date, \@end_date) % 60 AS varchar(2)), 2) - 呸,有人知道如何在 cmets 中转义 at 符号吗?
    【解决方案3】:

    我知道这个帖子比较老,最初的参与者可能不再看,但我偶然发现了它,并且最近已经编写了一些代码来做一些非常接近 jdiaz 要求的事情。结果以 D:H:M:S 格式呈现为字符串。

    第一步是以秒为单位获取时间跨度:

    DECLARE @ElapsedS INT
    SET @ElapsedS = DATEDIFF(second, @start_date, @end_date)
    

    现在创建以下标量函数:

    CREATE FUNCTION [dbo].[udfTimeSpanFromSeconds]
    (
        @Seconds int
    )
    RETURNS varchar(15)
    AS
    BEGIN
    DECLARE 
        --Variable to hold our result
          @DHMS varchar(15)
        --Integers for doing the math
        , @Days int --Integer days
        , @Hours int --Integer hours
        , @Minutes int --Integer minutes
        --Strings for providing the display
        , @sDays varchar(5) --String days
        , @sHours varchar(2) --String hours
        , @sMinutes varchar(2) --String minutes
        , @sSeconds varchar(2) --String seconds
    
    --Get the values using modulos where appropriate
    SET @Hours = @Seconds/3600
    SET @Minutes = (@Seconds % 3600) /60
    SET @Seconds = (@Seconds % 3600) % 60
    
    --If we have 24 or more hours, split the @Hours value into days and hours
    IF @Hours > 23 
    BEGIN
        SET @Days = @Hours/24
        SET @Hours = (@Hours % 24)
    END
    ELSE
    BEGIN
        SET @Days = 0
    END
    
    --Now render the whole thing as string values for display
    SET @sDays = convert(varchar, @Days)
    SET @sHours = RIGHT('0' + convert(varchar, @Hours), 2)
    SET @sMinutes = RIGHT('0' + convert(varchar, @Minutes), 2)
    SET @sSeconds = RIGHT('0' + convert(varchar, @Seconds), 2)
    
    --Concatenate, concatenate, concatenate
    SET @DHMS =  @sDays + ':' + @sHours + ':' + @sMinutes + ':' + @sSeconds
    
    RETURN @DHMS
    
    END
    

    现在将您的时间跨度输入到新创建的函数中:

    SELECT TimeSpan = dbo.udfTimeSpanFromSeconds(@ElapsedS)
    

    应该产生'1:09:19:01'

    【讨论】:

      【解决方案4】:

      DATEDIFF 可能返回不直观的值。例如,下面的两个日期相差一秒,但 DATEDIFF 使用下面的参数并解释为其他人在上面解释它返回 1 年:

      SELECT DATEDIFF(年, '2005-12-31 23:59:59', '2006-01-01 00:00:00')

      查看 DATEDIFF 的 MSDN 文档以了解其工作原理。

      【讨论】:

      • 好吧,如果您将精度定义为“年”,那么这里没有什么不直观的。如果你告诉数据库你想要第二精度,你应该得到你的 1。
      • “直观”是最通情达理的人所期望的。恕我直言,他们(可能没有阅读文档中的细则)会期望上面的值是 0 对 1。如果你已经活了 1 纳秒到 364 天、23 小时、59 分钟和59秒,你几“岁”? 0 而不是 1。即使您允许四舍五入到最接近的年份,小于 7 个月的任何时间都应该四舍五入到 0 岁。如果您说的是“年龄”(即出于法律目的)与“年龄”,那么您肯定会不舍入(你会截断又名舍入)。
      【解决方案5】:

      datediff(datepart, date1, date2);

      雷克斯的回答比较完整。

      【讨论】:

        【解决方案6】:

        这是在查询中格式化 datediff (50d 8h 35m) 的方式:

        Declare @Date1 as Datetime, @Date2 as Datetime
        Set @Date1 = '2005-01-01 08:00:00'
        Set @Date2 = '2005-02-20 16:35:30'
        
        Select
        CAST(DATEDIFF(Minute,@Date1, @Date2)/60/24 as Varchar(50)) ++ 'd ' ++ 
        CAST((DATEDIFF(Minute,@Date1, @Date2)/60)-((DATEDIFF(Minute,@Date1, @Date2)/60/24)*24) as Varchar(50)) ++ 'h ' ++
        CAST((DATEDIFF(Minute,@Date1, @Date2)) - (DATEDIFF(HOUR,@Date1, @Date2)*60) as Varchar(50)) ++ 'm' as FormattedDateDiff
        

        【讨论】:

          【解决方案7】:
          DECLARE @FirstDate DATETIME, @SecondDate DATETIME, @result VARCHAR(MAX)
          SELECT @FirstDate = '2017-03-01 09:54:00.637', @SecondDate = GETDATE()
          
          DECLARE @Day INT,@Month INT,@Hour INT, @Minute INT,@TotalSeconds INT,@Year INT
          SELECT @TotalSeconds = ABS(DATEDIFF(SECOND,@FirstDate,@SecondDate))
          
          -- Standard values in seconds
          DECLARE @YearSeconds INT, @MonthSeconds INT, @DaySeconds INT, @HourSeconds INT, @MinuteSeconds INT
          
          SELECT  @MinuteSeconds = 60
          SELECT  @HourSeconds = 60 * @MinuteSeconds 
          SELECT  @DaySeconds = 24 * @HourSeconds
          SELECT  @MonthSeconds = 30 * @DaySeconds
          SELECT  @YearSeconds = 12 * @MonthSeconds
          
          --SELECT @MinuteSeconds AS [Minutes], @HourSeconds AS [Hours], @DaySeconds AS [Day],@MonthSeconds AS [Month],@YearSeconds AS [Year]
          
          IF @TotalSeconds < @MinuteSeconds
          BEGIN
              SELECT @result = CAST(@TotalSeconds AS NVARCHAR(20)) + ' seconds ago' 
          END
          ELSE IF @TotalSeconds < @HourSeconds
          BEGIN
              SELECT @result = CAST(ABS(DATEDIFF(MINUTE,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' minutes ago' 
          END
          ELSE IF @TotalSeconds < @DaySeconds
          BEGIN
              SELECT @result = CAST(ABS(DATEDIFF(HOUR,@FirstDate,@SecondDate)) AS     NVARCHAR(20)) + ' hours ago' 
          END
          ELSE IF @TotalSeconds < @MonthSeconds
          BEGIN
              SELECT @result = CAST(ABS(DATEDIFF(DAY,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' days ago' 
          END
          ELSE IF @TotalSeconds < @YearSeconds
          BEGIN
              SELECT @result = CAST(ABS(DATEDIFF(MONTH,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' months ago' 
          END
          ELSE IF @TotalSeconds > @YearSeconds
          BEGIN
              SELECT @result = CAST(ABS(DATEDIFF(YEAR,@FirstDate,@SecondDate)) AS NVARCHAR(20)) + ' year ago' 
          END
          
          
          SELECT @result
          

          【讨论】:

          • 结果样本,“2 个月前”等
          猜你喜欢
          • 2012-12-09
          • 2011-04-28
          • 1970-01-01
          • 2013-04-25
          • 1970-01-01
          • 2020-04-11
          • 1970-01-01
          • 1970-01-01
          • 2020-11-14
          相关资源
          最近更新 更多