【问题标题】:Issues with T-SQL function to round time to earliest hourT-SQL 函数将时间舍入到最早小时的问题
【发布时间】:2012-04-24 20:01:17
【问题描述】:

我需要编写一个函数,在一个列中舍入时间以从其原始时间开始(例如:23:33:00.0000000 将是 23:00)并在另一列中舍入时间到下一个小时(例如: 23:33:00.0000000 将是 24:00),然后将这些新值插入到新列中。我在 How to Round a Time in T-SQL 的 Stack Overflow 上找到了这个函数,但我无法运行该函数。我不断收到此错误消息:'Msg 156,Level 15,State 1,Procedure RoundTime,Line 11 关键字'SELECT'附近的语法不正确。'

CREATE FUNCTION [dbo].[RoundTime] (@Time datetime, @RoundTo float)
RETURNS datetime
AS
BEGIN
   DECLARE @RoundedTime smalldatetime
   DECLARE @Multiplier float
   SET @Multiplier= 24.0/@RoundTo
   SET @RoundedTime= ROUND(CAST(CAST(CONVERT(varchar,@Time,121) AS datetime) AS float) * @Multiplier,0)/@Multiplier
   RETURN @RoundedTime
END
SELECT [dbo].[RoundTime] ('23:33',0.0)

我也尝试使用 SELECT dbo.roundtime('23:33',0.0) 运行它,但仍然没有任何乐趣。

所以我希望通过运行此函数来尝试找出如何缩短时间,但我什至无法运行它。而且我不知道如何让时间回到最早的时间点。我是否只需要从时间戳中提取小时,然后将该小时插入到它的新列中?或者有没有办法即时转换它然后将其插入新列?我正在使用 Sql Server 2008。

【问题讨论】:

    标签: sql sql-server-2008 tsql datetime


    【解决方案1】:

    函数必须存在才能引用它。在函数声明后添加 GO,将创建与使用分开。

    CREATE FUNCTION [dbo].[RoundTime] (@Time datetime, @RoundTo float)
    RETURNS datetime
    AS
    BEGIN
       DECLARE @RoundedTime smalldatetime
       DECLARE @Multiplier float
       SET @Multiplier= 24.0/@RoundTo
       SET @RoundedTime= ROUND(CAST(CAST(CONVERT(varchar,@Time,121) AS datetime) AS float) * @Multiplier,0)/@Multiplier
       RETURN @RoundedTime
    END
    GO
    
    SELECT [dbo].[RoundTime] ('23:33',0.0)
    

    【讨论】:

      【解决方案2】:

      我不确定为什么会出现语法错误,但是当我运行它时,会出现除以零的错误。我不认为该函数应该在第二个参数中使用 0 运行。但这让你无法四舍五入我认为。在这种情况下,您可以只使用 1 作为第二个参数,该参数向上舍入到下一小时,然后执行 dateadd -1 小时返回。 (或增强功能)。

      【讨论】:

      • 这是我发现的。我可以提取小时值并保留它或添加一个(如果它在 EndTime 列中):SELECT (DATEPART(HOUR, [StartTime]) / 1) ,[EndTime] FROM [DesignTest].[dbo]。 [Site_Availability_Stg] ORDER BY OutageDate ASC 这将带我到我现在要去的地方。感谢您的输入。非常感谢。
      【解决方案3】:

      SET @Multiplier= 24.0/@RoundTo 并且您将 0.0 传递给 @RoundTo 的值如果您传递 1.0 会发生什么?

      现在你已经运行了,删除这个函数并用这个替换它:

      CREATE FUNCTION [dbo].[RoundTime] 
      (
          @Time datetime, 
          @RoundTo float
      ) 
      RETURNS datetime 
      AS 
      BEGIN    
          DECLARE @RoundedTime datetime    
          DECLARE @Multiplier float    
          SET @Multiplier= 24.0/@RoundTo    
          SET @RoundedTime= FLOOR(CAST(CAST(CONVERT(varchar,@Time,121) AS datetime) AS float) * @Multiplier)/@Multiplier    
          RETURN @RoundedTime 
      END 
      

      @RoundedTime 变量从 smalldatetime 切换到 datetime 可以阻止它浪费时间。将Round 更改为Floor 可以获得您要查找的第一个号码,并且您知道您总是会增加一个小时。您可能想要重命名该函数以匹配它现在正在执行的操作...

      哦,第二个参数应该是1.0(SELECT [dbo].[RoundTime] ('23:33:45',1.0)

      【讨论】:

      • 现在我已经运行了函数(感谢 Joe),当我传入 1.0.0 时它返回 1900-01-02 00:00:00.000。这不是我所希望的。
      • @Lynn - 将 Joe 的答案标记为正确,并针对新问题打开一个新问题,说明您想要的行为。
      • 我确实将其标记为正确,并感谢乔让我继续前进。我又花了几分钟,才回答了我问题的另一部分。
      猜你喜欢
      • 2021-12-15
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多