2010-11-11 8 views
5

Tengo una consulta mySql que agrega cierto intervalo de tiempo al campo datetime.sql - sumando el intervalo de tiempo con la omisión de cierto período

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

Ahora, necesito para detectar si la nueva hora de finalización está entre algunas horas (digamos 20:00-06:00), que debe ser excluido del cálculo.

Ie. si la terminación anterior es hoy, 19:58 y estamos agregando 4 minutos, la nueva finalización debe ser mañana, 06:02

La dificultad adicional es que la cantidad de tiempo para agregar puede ser mayor a 24 horas. Así que si el viejo final es hoy, 19.00 y estamos añadiendo 24 horas, nuevo final debe ser pasado mañana, 15.00 (que suena como un título de una película mala;)

¿Hay manera de lograr esto en mysql? En una consulta? También estaba pensando en procedimientos almacenados, pero no tengo ninguna experiencia con.

algunos datos de prueba:

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'); 

Respuesta

3
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 significa que su tiempo libre comienza en 20:00, INTERVAL 10 HOUR significa que tiene una duración de 10 horas (hasta 20:0006:00). Ajustar en consecuencia.

Actualización:

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 
+0

y donde es 48? o 72? me gustaría tener un cambio enorme aquí –

+0

¿Qué es '48' o' 72' y por qué crees que deberían estar aquí? – Quassnoi

+0

Horas para agregar como intervalo. Debido a que t_ending es DATETIME, no TIME –

2

era un poco complicado en una sola consulta, pero esta consulta debería funcionar:

 
-------------- 
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 | 
+---------------------+---------------------+--------------+---------------------+ 

Editar: aquí hay una versión más corta:

 
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 
; 
+1

Bagh. Publicidad. – thomaspaulb

1

Y esto es mío:

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 
Cuestiones relacionadas