【问题标题】:SQL Server - Round TIME values to the next minuteSQL Server - 将 TIME 值舍入到下一分钟
【发布时间】:2012-03-05 16:15:39
【问题描述】:

我发现了很多关于“向下”时间值四舍五入的帖子(例如https://stackoverflow.com/a/6667041/468823),但我还有另一个问题:我想四舍五入到较高的分钟而不是较低的分钟,我该怎么做?

我的代码:

SELECT

 PA.ORE AS TOT_HOURS,  
 CAST(CAST(PA.ORA_INIZIO AS DATETIME) AS TIME) AS BEGIN_TIME,
 CAST(dateadd(minute, datediff(minute, 0, (CAST(PA.ORA_INIZIO AS DATETIME))), 0) AS TIME) AS BEGIN_TIME_ROUNDED


FROM PRG_ATTIVITA PA INNER JOIN PRG_TIPI_ATTIVITA PTA ON  PA.ID_TIPO_ATTIVITA = PTA.ID_TIPO_ATTIVITA
                     INNER JOIN PER_ANAGRAFICA PAN ON PA.ID_DIPENDENTE = PAN.ID_DIPENDENTE
WHERE PA.ID_PROGETTO = 1431 and pta.DESCR_TIPO_ATTIVITA like 'F-%remoto%' and ID_ATTIVITA = 41772 

ORDER BY  PA.DATA_ATTIVITA

我的结果如下:

    TOT_HOURS   BEGIN_TIME          BEGIN_TIME_ROUNDED
    1.50        15:59:59.9970000    15:59:00.0000000

我想要 BEGIN_TIME_ROUNDED = 16:00:00.0000000

注意事项: 1. 我必须转换我的数据 { CAST(PA.ORA_INIZIO AS DATETIME) } 因为在数据库中我有时间数据作为浮点值 2.BEGIN_TIME是我的时间值转换后的真实值

【问题讨论】:

    标签: sql sql-server-2008 tsql rounding sqldatetime


    【解决方案1】:

    对 SQL Server 的了解不足以立即回答,但如果没有人提供更实际的方法来做到这一点,那么您可以在四舍五入之前将值添加 1 分钟。或者如果您还需要正确处理整数输入值,则添加 0.999 分钟。

    【讨论】:

      【解决方案2】:

      只需 CAST 到 smalldatetime 以四舍五入到最接近的分钟

      SELECT 
          CAST(CAST('15:59:59.9970000' AS time) AS smalldatetime),
          CAST(CAST('15:59:30.0030000' AS time) AS smalldatetime),
          CAST(CAST('15:59:30.0000000' AS time) AS smalldatetime),
          CAST(CAST('15:59:29.9970000' AS time) AS smalldatetime),
          CAST(CAST('15:59:00.0030000' AS time) AS smalldatetime)
      

      DATEADD/DATEDIFF 用于截断一些时间单位

      编辑、误读问题

      只需修改您当前的 CAST

      CAST(
       DATEADD(minute,
               DATEDIFF(minute, 
                        0, 
                        CAST(PA.ORA_INIZIO AS DATETIME)
                       ) + 1, 
               0
               )
           AS TIME)
      

      【讨论】:

      • -1 这根本不能回答问题。 OP 希望总是四舍五入到最接近的分钟,您发布的解决方案通常会四舍五入到最接近的分钟,即您的 select 语句的最后 2 列向下舍入到 15:59 而不是 16:00。跨度>
      • @GarethD:修复它,我错过了。谢谢
      • 有问题 '20:30' 会四舍五入到 '20:31'
      • 这是一个天花板问题。 20:30 不应四舍五入。至少不是我如何阅读这个问题。您只是四舍五入并增加了 1 分钟
      【解决方案3】:

      如果您想将 DATETIME d 舍入到最接近的分钟,您可以这样做:

      CONVERT(DATETIME, CONVERT(SMALLDATETIME,
        DATEADD(minute, CASE WHEN d = CONVERT(SMALLDATETIME, d) THEN 0 ELSE 1 END,
        d)))
      

      【讨论】:

        【解决方案4】:
        SELECT  DATEADD(MINUTE, CEILING(DATEDIFF(SECOND, 0, CAST(CAST(PA.ORA_INIZIO AS DATETIME) AS TIME)) / 60.0), DATEDIFF(DAY, 0, PA.ORA_INIZIO)) AS BEGIN_TIME_ROUNDED
        

        编辑

        正如评论中指出的那样,这会在 0 到 1 秒之间失败。这可以通过简单地将上限的精度从秒更改为毫秒来解决:

        SELECT  PA.ORA_INIZIO,
                DATEADD(MINUTE, 
                    CEILING(DATEDIFF(MILLISECOND, 0, CAST(PA.ORA_INIZIO AS TIME)) / 60000.0),
                    DATEDIFF(DAY, 0, PA.ORA_INIZIO)) AS BEGIN_TIME_ROUNDED
        FROM (VALUES 
                (CONVERT(DATETIME, '20211126 15:59:00.997')), 
                (CONVERT(DATETIME, '20211126 15:59:00.004'))
            ) AS PA (ORA_INIZIO);
        

        这给出了:

        ORA_INIZIO BEGIN_TIME_ROUNDED
        2021-11-26 15:59:59.997 2021-11-26 16:00:00.000
        2021-11-26 15:59:00.003 2021-11-26 16:00:00.000

        【讨论】:

        • 这在时间列大于0秒小于1秒时不起作用。在这种情况下,语法将向下舍入
        • @t-clausen.dk 感谢您的反馈。我已经修改了答案来处理这种情况。
        【解决方案5】:
        DECLARE @ datetime = '2021-11-26 00:00:00.997'
        SELECT dateadd(minute, ceiling(cast(@ as float) * 1440),0) ceilingminute
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多