代码之家  ›  专栏  ›  技术社区  ›  ts.

sql-添加跳过某个时段的时间间隔

  •  5
  • ts.  · 技术社区  · 14 年前

    我有一个mySql查询,它添加了特定的时间间隔到datetime字段。

    UPDATE table T 
       SET T.ending = DATE_ADD(T.ending, INTERVAL T.hours * 3600 * some_other_variable_factors SECONDS)) 
    

    现在,我需要检测新的结束时间是否在几个小时之间(比如说20:00到06:00),这应该排除在计算之外。

    也就是说,如果旧的结局是今天,19:58,我们加上4分钟,新的结局应该是明天,06:02

    额外的困难是,增加的时间可以超过24小时。 所以如果旧的结尾是今天19:00,我们加上24小时,新的结尾应该是后天15:00 (听起来像是一部非常糟糕的电影的片名;)

    在mysql中有实现这一点的方法吗?一个问题?我也在考虑存储过程,但我没有任何经验。

    一些测试数据:

       CREATE TABLE IF NOT EXISTS `tt` (
          `source` datetime NOT NULL,
          `hours` int(11) NOT NULL,
          `off_start` int(11) NOT NULL,
          `off_long` int(11) NOT NULL,
          `correct` datetime NOT NULL    
        ) ENGINE=InnoDb;
    
    
        INSERT INTO `tt` (`source`, `hours`, `off_start`, `off_long`, `correct`) VALUES
        ('2010-11-11 12:00:00', 1, 20, 10, '2010-11-11 13:00:00'),
        ('2010-11-11 19:00:00', 1, 20, 10, '2010-11-12 06:00:00'),
        ('2010-11-11 19:00:00', 2, 20, 10, '2010-11-12 07:00:00'),
        ('2010-11-11 19:00:00', 3, 20, 10, '2010-11-12 08:00:00'),
        ('2010-11-11 19:00:00', 24, 20, 10, '2010-11-13 15:00:00'),
        ('2010-11-11 19:00:00', 48, 20, 10, '2010-11-15 11:00:00'),
        ('2010-11-11 19:00:00', 72, 20, 10, '2010-11-17 07:00:00');
    
    3 回复  |  直到 14 年前
        1
  •  3
  •   Quassnoi    14 年前
    SELECT  CASE
            WHEN HOUR((t_ending + INTERVAL some_other_variable_factors HOUR)  - INTERVAL 20 HOUR) < 10 THEN
                    t_ending + INTERVAL some_other_variable_factors HOUR + INTERVAL 10 HOUR
            ELSE
                    t_ending + INTERVAL some_other_variable_factors HOUR
            END
    FROM    mytable
    

    INTERVAL 20 HOUR 意思是你的休息时间从 20:00 , INTERVAL 10 HOUR 意思是持续10小时( 20: 00个 直到 06:00 ). 相应调整。

    更新:

    SET @hours = 54;
    
    SELECT  CAST('2010-01-01 15:00:00' + INTERVAL @hours HOUR AS DATETIME);
    
    --
    2010-01-03 21:00:00
    
    
    SELECT  CASE
            WHEN HOUR(CAST('2010-01-01 15:00:00' + INTERVAL @hours HOUR AS DATETIME)  - INTERVAL 20 HOUR) < 10 THEN
                    CAST('2010-01-01 15:00:00' + INTERVAL @hours HOUR + INTERVAL 10 HOUR AS DATETIME)
            ELSE
                    CAST('2010-01-01 15:00:00' + INTERVAL @hours HOUR AS DATETIME)
            END;
    
    --
    2010-01-04 07:00:00
    
        2
  •  2
  •   Bruno Gautier    14 年前

    在一个查询中有点棘手,但是这个查询应该可以工作:

    --------------
    SELECT source, correct, hours_to_end, (source + INTERVAL hours_to_end HOUR) ending
    FROM (
        SELECT source, correct
            , LEAST(hours, hours_to_off)
              + (((hours_left - MOD(hours_left, on_long)) / on_long) * 24
              + off_long
              + MOD(hours_left, on_long)) * overlap hours_to_end
        FROM (
            SELECT source, correct, hours, on_long, off_long, hours_to_off
                , GREATEST(0, hours - hours_to_off) hours_left
                , IF(hours - hours_to_off >= 0, 1, 0) overlap
            FROM (
                SELECT source, correct, hours, off_long
                    , (24 - off_long) on_long
                    , HOUR(TIMEDIFF(DATE(source) + INTERVAL off_start HOUR, source)) hours_to_off
                FROM tt
              ) t
          ) t
      ) t
    --------------
    
    +---------------------+---------------------+--------------+---------------------+
    | source              | correct             | hours_to_end | ending              |
    +---------------------+---------------------+--------------+---------------------+
    | 2010-11-11 12:00:00 | 2010-11-11 13:00:00 |       1.0000 | 2010-11-11 13:00:00 |
    | 2010-11-11 19:00:00 | 2010-11-12 06:00:00 |      11.0000 | 2010-11-12 06:00:00 |
    | 2010-11-11 19:00:00 | 2010-11-12 07:00:00 |      12.0000 | 2010-11-12 07:00:00 |
    | 2010-11-11 19:00:00 | 2010-11-12 08:00:00 |      13.0000 | 2010-11-12 08:00:00 |
    | 2010-11-11 19:00:00 | 2010-11-13 15:00:00 |      44.0000 | 2010-11-13 15:00:00 |
    | 2010-11-11 19:00:00 | 2010-11-15 11:00:00 |      88.0000 | 2010-11-15 11:00:00 |
    | 2010-11-11 19:00:00 | 2010-11-17 07:00:00 |     132.0000 | 2010-11-17 07:00:00 |
    +---------------------+---------------------+--------------+---------------------+
    

    编辑 :以下是较短版本:

    SELECT source, correct
      , source
        + INTERVAL LEAST(hours, hours_to_off)
          + IF(hours-hours_to_off >= 0
            ,(hours-hours_to_off-MOD(hours-hours_to_off, on_long))/on_long*24
              + off_long + MOD(hours-hours_to_off, on_long)
            ,0) HOUR ending
    FROM (
        SELECT source, correct, hours, off_long, (24-off_long) on_long
          , HOUR(TIMEDIFF(DATE(source)+INTERVAL off_start HOUR, source)) hours_to_off
        FROM tt
      ) t
    ;
    
        3
  •  1
  •   littlegreen    14 年前

    这是我的:

    CREATE PROCEDURE do_update()
    BEGIN
    
    DECLARE @offhoursperday, @hours, @days, @remaininghours INT
    DECLARE @offhoursstart, @offhoursend TIME
    
    SET @offhoursstart = CAST('22:00' AS TIME)
    SET @offhoursend = CAST('06:00' AS TIME)
    SET @hours = 54
    SET @days = @hours / (24 - @offhoursperday)
    SET @remaininghours = @hours % (24 - @offhoursperday)
    
    UPDATE table T 
       SET T.ending =  
       CASE 
           WHEN ((HOUR(TIMEDIFF(@offhoursstart, TIME(T.ending))) + 24) % 24) < @remaininghours
           THEN DATE_ADD(DATE_ADD(T.ending, INTERVAL @days DAY), INTERVAL @remaininghours HOUR)
           ELSE DATE_ADD(DATE_ADD(T.ending, INTERVAL @days DAY), INTERVAL (@remaininghours + @offhoursperday) HOUR)
       END
    
    END