2010-11-11 22 views
5

J'ai une requête mySql qui ajoute un certain intervalle de temps au champ date/heure.sql - ajout d'un intervalle de temps avec saut de certaine période

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

Maintenant, je dois détecter si nouveau temps de fin est entre quelques heures (disons 20h00-6h00), qui devrait être exclu du calcul.

Ie. si l'ancienne fin est aujourd'hui, 19:58 et nous ajoutons 4 minutes, la nouvelle fin devrait être demain, 06:02

La difficulté supplémentaire est que la durée d'ajout peut être supérieure à 24 heures. Donc si l'ancienne fin est aujourd'hui, 19h00 et nous ajoutons 24 heures, la nouvelle fin devrait être après-demain, 15,00 (ce qui sonne comme un titre d'un film vraiment mauvais;)

Y at-il moyen d'y parvenir en mysql? Dans une requête? Je pensais aussi aux procédures stockées, mais je n'ai aucune expérience avec.

Certaines données de 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'); 

Répondre

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 signifie que votre temps libre commence à 20:00, INTERVAL 10 HOUR signifie qu'il dure 10 heures (jusqu'à 20:0006:00). Ajuste en accord.

Mise à jour:

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

et où il est 48? ou 72? Je voudrais évoquer avoir énorme commutateur ici –

+0

Qu'est-ce que «48» ou «72» et pourquoi vous pensez qu'ils devraient être ici? – Quassnoi

+0

Heures à ajouter en tant qu'intervalle. Parce que t_ending est DATETIME, pas TIME –

2

était un peu difficile dans une seule requête, mais cette requête devrait fonctionner:

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

Modifier: voici une version plus courte:

 
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. La publicité. – thomaspaulb

1

Et c'est le mien:

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