2009-10-10 6 views
3

Si nous avons une minuterie qui commence à partir de CURRENT_TIMESTAMP - 1 heure, nous pouvons simplement calculer la différence et le retour de 3600 secondes ont passé. Que se passe-t-il si nous voulons que la minuterie ne compte que pendant les heures de la journée et ne dise que le travail pendant le jour de la semaine ou les jours spécifiés. Regardez le code ci-dessous pour voir Créer statment pour obtenir une meilleure compréhensionComplexe MySQL Timer

CREATE TABLE `timer` (
    `Id`    BIGINT  NOT NULL AUTO_INCREMENT, 
    `title`   VARCHAR(100) NOT NULL, 
    `startAt`  DATETIME  NOT NULL, 

    `startTime`  TIME     DEFAULT NULL, 
    `endTime`  TIME     DEFAULT NULL, 

    `monday`   BOOLEAN     DEFAULT 1, 
    `tuesday`  BOOLEAN     DEFAULT 1, 
    `wednesday`  BOOLEAN     DEFAULT 1, 
    `thursday`  BOOLEAN     DEFAULT 1, 
    `friday`   BOOLEAN     DEFAULT 1, 
    `saturday`  BOOLEAN     DEFAULT 1, 
    `sunday`   BOOLEAN     DEFAULT 1, 

    `dateReg`  TIMESTAMP  NOT NULL DEFAULT CURRENT_TIMESTAMP, 

    PRIMARY KEY (`Id`) 

) ENGINE=InnoDB AUTO_INCREMENT=1 COMMENT 'Timer'; 

Note: The startime and endtime represent the hours the timer will take into account when counting seconds from two dates. The timer as represented above does not have a endtime meaning it will never stop

Maintenant, on dit que cela peut être fait dans une requête, et je suis sûr que ils ont raison, mais je personnellement belaive il sera beaucoup plus facile et mieux dans une fonction stockée:

CREATE FUNCTION `TIMEPASSED`(iId BIGINT(100)) RETURNS BIGINT(20) 
BEGIN 
    DECLARE sTime TIME; 
    DECLARE eTime TIME; 
    DECLARE startAt DATETIME; 

    #Get the Results from the Database and put them into the variables 
    SELECT timer.startTime, timer.endTime, timer.startAt INTO sTime, eTime, startAt FROM tickets 
    WHERE timer.Id = iId; 

    #if the start time is null then return the difference between the reset time and now 
    IF sTime IS NULL 
     THEN RETURN (UNIX_TIMESTAMP(CURRENT_TIMESTAMP) - UNIX_TIMESTAMP(startAt)); 
    END IF; 

RETURN NULL; 

END 

la fonction ci-dessus ne retourne la pleine ammount de secondes qui se sont écoulées scince la minuterie a été lancée si le startTime IS NULL.

permet maintenant faire la requête d'insertion

INSERT INTO timer VALUES(NULL, 'mytimer', CURRENT_TIMESTAMP, 09:00, 18:00, 1, 1, 1, 1, 1, 0, 0, CURRENT_TIMESTAMP); 

La requête ci-dessus suggèrent que la minuterie commence à partir CURRENT_TIME et ne compte que quelques secondes 9h00-18h00 et ne fonctionne que pour du lundi au vendredi.

La requête de sélection, (Trier par qui est important ici)

SELECT *, TIMEPASSED(Id) as passed FROM timer ORDER BY passed DESC 

En général: Je veux connaître les secondes se sont écoulées pendant le temps alloué par le temps entré

Tout refrences aux mathématiques de base dans ce sujet sera très appréciée. Je peux travailler dehors puis

Merci: D

+1

FYI: L'appel de fonctions corrélées dans les clauses SELECT peut avoir un impact négatif sur les performances - la base de données appellera cette fonction pour chaque ligne renvoyée. –

+0

@rexem: Oh sry rexem je vois ce que tu veux dire .. Sry pour ne pas être clair: Le début et la fin représentent le temps qu'il compte chaque jour. Cela ne représente pas l'heure à laquelle la minuterie s'arrêtera. Le temporisateur ne s'arrêtera jamais –

+0

Si je comprends la question, ne seriez-vous pas simplement entrer l'heure de début, puis soustrayez-le de la fonction NOW() pour obtenir le temps passé? Vous pouvez également mettre en forme l'heure dans n'importe quel format? SELECT (UNIX_TIMESTAMP (CURRENT_TIMESTAMP) - UNIX_TIMESTAMP (startAt)) AS lapsedTime FROM ... –

Répondre

3

Si je comprends bien, je pense un bon algorithme à utiliser dans votre procédure stockée serait:

  1. Démarrer un décompte à zéro.
  2. Si aujourd'hui est la même date que dateReg, et que le jour de la semaine correspondant est true, ajoutez le nombre maximum (startTime, dateReg's time) - min (endTime, heure actuelle).
  3. Sinon, si aujourd'hui après la date de dateReg:
    1. Si le jour correspondant de dateReg de la semaine est vrai, et le temps de dateReg est avant endTime, ajouter au décompte maximum (temps de startTime, dateReg) - endTime.
    2. Si le jour de la semaine correspondant au jour actuel est true et que l'heure actuelle est après startTime, ajoutez au paramètre startTime - min (endTime, heure actuelle).
  4. Stocke endTime - startTime dans wholeDay.
  5. Si lundi est vrai, calculez le nombre de lundis entre la date de dateReg et la date actuelle, exclusif. * Ajoutez ce nombre multiplié par wholeDay au total. Répétez pour chaque jour de la semaine.
  6. Renvoie le résultat.

* Ceci est un autre problème en soi. Une façon de le faire serait de calculer le nombre de semaines complètes après la semaine de dateReg et avant la semaine en cours, puis ajouter 1 si le jour après le DoW de DayReg (jour de la semaine) est avant le DoW en question, et ajouter 1 si le jour avant que le DoW actuel ne soit après le DoW en question.

+0

@Kev: Vous êtes sur la bonne voie: D ... J'ai presque une solution de travail en MySQL, je vais l'afficher à la fin de la prime ... Comme je voudrais quelqu'un pour l'obtenir: D –

+0

Merci . Bon temps. :) – Kev

+0

A cause de votre concept .. j'ai exactement le même concept que je vais accepter: D –