2010-11-11 13 views
5

Ho una query mySql che aggiunge un certo intervallo di tempo al campo datetime.sql - aggiunta intervallo di tempo con salti di determinati periodi

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

Ora, ho bisogno di rilevare se nuovo tempo finale è tra alcune ore (diciamo 20:00-06:00), che dovrebbero essere esclusi dal calcolo.

Ie. se il vecchio finale è oggi, 19:58 e stiamo aggiungendo 4 minuti, il nuovo finale dovrebbe essere domani, 06:02

Ulteriore difficoltà è che il tempo di aggiunta può essere maggiore di 24 ore. Quindi se il vecchio termine è oggi, alle 19.00 e aggiungiamo 24 ore, il nuovo fine dovrebbe essere dopodomani, 15.00 (che suona come un titolo di un film davvero brutto;)

C'è modo di ottenere questo in mysql? In una query? Stavo anche pensando alle stored procedure, ma non ho alcuna esperienza con.

Alcuni dati di test:

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

risposta

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 il vostro tempo libero inizia alle 20:00, INTERVAL 10 HOUR significa che ha una durata di 10 ore (fino 20:0006:00). Regolare di conseguenza.

Aggiornamento:

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

e dove è 48? o 72? vorrei fare a meno di avere un enorme cambiamento qui –

+0

Cosa sono '48' o' 72' e perché pensi che dovrebbero essere qui? – Quassnoi

+0

Ore da aggiungere come intervallo. Perché t_ending è DATETIME, non TIME –

2

era un po 'difficile in una singola query, ma questa query dovrebbe funzionare:

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

Edit: qui è una versione più breve:

 
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. Pubblicità. – thomaspaulb

1

E questo è il mio:

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 
Problemi correlati