3

DATETIME在 mySQL ( fromStamp) 中有一个字段,其中包含有效的日期/时间戳。我需要能够将分钟向上舍入到下一个 6 分钟间隔。秒数应被忽略或视为 :00

因此,如果我的 DATETIME 是,2013-01-31 13:07:17我需要将结果2013-01-31 13:12:00 排除在 :00 和 :06 以及 :31 和 :36 之间的时间之外,那些需要四舍五入DOWN

 :00-06 round DOWN to 00
 :07-12 round UP to 12
 :13-18 round UP to 18
 :19-24 round UP to 24
 :24-30 round UP to 30
 :31-36 round DOWN to 30
 :37-42 round UP to 42
 :43-48 round UP to 48
 :49-54 round UP to 54
 :55-00 round UP to 00

我找到了一种合理的方法来选择性地向下舍入:

SELECT
  fromStamp, 
  CONCAT(DATE_FORMAT(`fromStamp`, '%Y-%m-%d'), ' ',
         SEC_TO_TIME((TIME_TO_SEC(`fromStamp`) DIV 360) * 360))
FROM `table` 
WHERE (
    DATE_FORMAT(`fromStamp`, '%i') BETWEEN 0 AND 6 
    OR DATE_FORMAT(`fromStamp`, '%i') BETWEEN 31 AND 36
);

有没有一种很好的方法可以将其他所有内容四舍五入到接下来的 6 分钟间隔?(我觉得我错过了一些简单的东西)

更新

所以我将采用@mellamokb 的解决方案,但他关于秒的评论是正确的,它确实发挥了作用。

2013-01-22 12:24:13 的 DATETIME 向上舍入到 12:30,这不是所需要的,所以我首先要做:

UPDATE table SET fromStamp = CONCAT(DATE_FORMAT(fromStamp, '%Y-%m-%d %h:%i'), ':00'); 

摆脱几秒钟,然后他的查询得到了我正在寻找的东西。

4

3 回答 3

2

向上舍入是非常相似的逻辑,除了您添加1移位到下一个最近的6-minute间隔。我还减去1TIME_TO_SEC作为校正因子,否则边界值,例如06:00在下一个 6 分钟间隔上移,即12:00.

SEC_TO_TIME( ( (TIME_TO_SEC(`fromStamp`) - 1) DIV 360 + 1) * 360))
                                                      ^^^ add one

要将两者结合起来,请使用CASE语句来控制每条记录使用哪种形式的舍入:

SELECT
  fromStamp, 
  CASE WHEN
    DATE_FORMAT(`fromStamp`, '%i') BETWEEN 0 AND 6 
    OR DATE_FORMAT(`fromStamp`, '%i') BETWEEN 31 AND 36
  THEN
    CONCAT(DATE_FORMAT(`fromStamp`, '%Y-%m-%d'), ' ',
         SEC_TO_TIME((TIME_TO_SEC(`fromStamp`) DIV 360) * 360))
  ELSE
    CONCAT(DATE_FORMAT(`fromStamp`, '%Y-%m-%d'), ' ',
         SEC_TO_TIME(((TIME_TO_SEC(`fromStamp`) - 1) DIV 360 + 1) * 360))
  END
FROM `table`

演示

于 2013-01-31T13:48:30.320 回答
1

根据提供的标准,我认为处理这种奇怪类型的舍入的最直接方法是:

 SELECT `fromStamp`
      , DATE_FORMAT(`fromStamp`,'%Y-%m-%d %H') + INTERVAL
        CASE
            WHEN TIME_FORMAT(`fromStamp`,'%i') <=  6 THEN  0  -- round DOWN
            WHEN TIME_FORMAT(`fromStamp`,'%i') <= 12 THEN 12  -- round up
            WHEN TIME_FORMAT(`fromStamp`,'%i') <= 18 THEN 18  -- round up
            WHEN TIME_FORMAT(`fromStamp`,'%i') <= 24 THEN 24  -- round up
         -- WHEN TIME_FORMAT(`fromStamp`,'%i') <= 30 THEN 30  -- round up
            WHEN TIME_FORMAT(`fromStamp`,'%i') <= 36 THEN 30  -- round DOWN
            WHEN TIME_FORMAT(`fromStamp`,'%i') <= 42 THEN 42  -- round up
            WHEN TIME_FORMAT(`fromStamp`,'%i') <= 48 THEN 48  -- round up
            WHEN TIME_FORMAT(`fromStamp`,'%i') <= 54 THEN 54  -- round up
            WHEN TIME_FORMAT(`fromStamp`,'%i') >= 55 THEN 60  -- round up
        END MINUTE AS rnd_fromStamp

对于未来的审稿人来说,这似乎是表达正在发生的事情的最直接的方式,他们会想知道“该声明对 fromStamp 做了什么塑料?”

可能会有稍快(更有效)的算法,但我认为这些算法中的任何一个都不会更优雅,或者像这样容易阅读和理解。

于 2013-01-31T14:40:40.920 回答
0

这我用于四舍五入到分钟

SELECT MINUTE(SEC_TO_TIME(((TIME_TO_SEC(call_duration)) DIV 60 +1)*60)) call_duration FROM call_log

于 2015-03-26T06:56:56.183 回答