Fonctions sur DATETIME avec mySQL

zoltanEpita
Invité n'ayant pas de compte PHPfrance

15 oct. 2005, 17:53

Bonjour à tous!

Je suis coincé dans un projet que je développe, dans lequel je dois faire des calculs statistiques sur mes données en base.

Voilà le problème :

J'ai deux données de type DATETIME
par exemple : 2005-11-05 15:03:52 et 2005-11-16 02:17:22

Je voudrais par une requête SQL déterminer le nombre de minutes qui se sont écoulées de 17h à 18h (par exemple) entre ces deux dates.

Celà fait déjà quelques temps que je suis plongé dans la doc de mySQL mais je n'arrive pas à voir comment je peux faire ça.

Si quelqu'un pouvait m'aider, je lui serais vraiment très reconnaissant parce que là je commence à désespérer .... lol

J'attends vos idées avec impatience.

Merci d'avance

Zoltan

Mammouth du PHP | 19672 Messages

15 oct. 2005, 18:05

Tu devrais regarder ce sujet de la FAQ
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

zoltanEpita
Invité n'ayant pas de compte PHPfrance

15 oct. 2005, 18:29

Merci pour le lien.

Malheuresement j'ai regardé et ce FAQ ne contient pas d'élément pour m'aider à ce que je veux faire.

Je pense qu'il faudrai combiner plusieurs fonctions dans la requête, avec des BEETWEN, des INTERVAL, etc ...

Mais je ne vois vraiment pas comment mettre ça en forme.

Si vous avez des éléments de réponses n'hésitez pas.

Merci!

Mammouth du PHP | 19672 Messages

15 oct. 2005, 18:40

Pour une différence en minutes, tu pourrais t'inspirer de ceci:

Code : Tout sélectionner

SELECT (TIME_TO_SEC('2005-10-01 15:45:00') - TIME_TO_SEC('2005-10-01 15:42:00')) / 60
Le résultat de cette requête va te retourner 3.00
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

zoltanEpita
Invité n'ayant pas de compte PHPfrance

16 oct. 2005, 15:48

Ok merci.

Je suis d'accord avec ça mais comment restreindre la durée écoulée juste dans un créneau horaire, genre de 15h à 16h.

En fait dans le projet plusieurs tranches horaires sont définies, et on voudrait savoir le le temps écoulé pour un tranche horaire donnée entre deux dates ....

Si quelqu'un voit comment faire ça, merci d'avance.

Mammouth du PHP | 19672 Messages

16 oct. 2005, 16:08

BOn, là, je t'ai illustré la manière de récupérer un nombre de minutes qui à la limite n'a même pas besoin d'une base de données. Maintenant, il faut dans un premier temps remplacer les valeurs que j'ai mises en dur dans la requête par les noms des champs correspondant et éventuellement ajouter des clauses restrictives sur les lignes à vérifier ou à exclure.

Quelle est exactement la structure de ta table (des tables s'il y en a plusieurs en cause) et donne un exemple de ce que tu veux obtenir.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

zoltanEpita
Invité n'ayant pas de compte PHPfrance

16 oct. 2005, 16:39

voici la strucuture de la table :

CREATE TABLE `alertes_monitoring` (
`alert_id` BIGINT NOT NULL AUTO_INCREMENT ,
`si_id` INT NOT NULL ,
`debut_prb` DATETIME NOT NULL ,
`fin_prb` DATETIME DEFAULT '1000-01-01 00:00:00' NOT NULL ,
PRIMARY KEY ( `alert_id` )
);

Je voudrais pour un enregistrement donné, avec par exemple:
debut_prb = 2005-02-22 14:05:20 et
fin_prb = 2005-02-26 15:54:22

déterminer le nombre de minutes écoulées entre ces deux dates dans une tranche horaire particulière (15h à 16h par exemple).

Dans notre exemple, il y aurait 294 minutes écoulées dans la tranche horaire 15-16h (60 + 60 + 60 + 60 + 54)

Comment modéliser ça sous la forme d'une requête SQL ....

J'espère avoir éclairci le problème.

Merci pour vos suggestions.
[/code]

Mammouth du PHP | 19672 Messages

16 oct. 2005, 16:57

BOn, je suis pas certain d'avoir bien compris quel champ devait se situer endans une tranche horaire particulière, mais voilà un point de départ:

Code : Tout sélectionner

SELECT ((TIME_TO_SEC(debut_prb) - TIME_TO_SEC(fin_prb)) / 60) AS duree FROM `alertes_monitoring` WHERE HOUR(debut_prb) BETWEEN 15 AND 16
Va te sortir la durée entre l'heure de début et l'heure de fin pour toutes les lignes dont le début est entre 15 et 16. (à tester)
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

zoltanEpita
Invité n'ayant pas de compte PHPfrance

16 oct. 2005, 17:28

C'est un bon début mais ce n'est pas encore ça.

Il est vrai que je pourrais résoudre ce problème de manière algorithmique mais ça serait assez lourd, alors que je suis sûr qu'on peut obtenir le calcul avec une requête SQL combinant les fonctions appropriées.

Pour résumer:

on une tranche horaire (15h à 16h par exemple) - > info qui ne se situe pas en base

On détermine pour chaque jour, du jour de début au jour de fin compris, le nombre de minutes qu'on a de 15h à 16h et on fait le cumul.

- Si la date de début commence par exemple à 20h, il y aura 0 minutes de 15h à 16h pour ce jour

- Si la date de fin est à 15h22, on aura 22 minutes du créneau horaire pour ce jour

- Si la date de début est le 23/05 et la date de fin le 26/05, on additionne le nombre de minutes de 15h à 16h pour chaque jour (23 + 24 +25 +26)

Dans ce cas les 24 et 25 auront chacun 60 minutes du créneau horaire car ce sont des jours complets.



Exemple concret :
date de début le 23/05/2005 à 18:05:57
date de fin le 28/05/2005 à 12:56:11
tranche horaire désirée de 15 à 16h

le 23 on a 0 min du créneau horaire
le 24 on a 60 min du créneau horaire
le 25 on a 60 min du créneau horaire
le 26 on a 60 min du créneau horaire
le 27 on a 60 min du créneau horaire
le 28 on a 0 min du créneau horaire

Ce qui nous fait un total de (0+60+60+60+0) 240 minutes de créneau horaire entre ces 2 dates

J'espère m'être mieux exprimé.

Merci pour vos idées.

Mammouth du PHP | 19672 Messages

16 oct. 2005, 18:19

C'est effectivement beaucoup plus clair et le titre du message en est d'autant plus justifié :-k

Tel quel, je ne vois pas, mais je vais y réfléchir, la question est tordue à souhait :D
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

zoltanEpita
Invité n'ayant pas de compte PHPfrance

20 oct. 2005, 16:47

Oui c'est vrai que c'est pas évident, c'est le genre de problème qu'on peut mettre en question facultative de partiel pour départager les ex-aequo! lol

Je vais commencer à réfléchir à une solution algoritmique car apparemment personne n'a d'idée sur comment on peut y arriver via une requête SQL.

Si quelqu'un a un déclic ou une piste je suis preneur.

Merci d'avance

zoltanEpita
Invité n'ayant pas de compte PHPfrance

28 oct. 2005, 14:59

Bon voilà j'ai développé l'algo qui répond exactement au problème, je le poste ici, ça peux toujours servir quelqu'un.

<?php
	
	/*
	
		nom         :  getNbMinutes()
		
		description :  détermine pour chaque jour, du jour de début au jour de fin compris, 
			       le nombre de minutes qu'on a dans la tranche horaire et on fait le cumul
		
		paramètres  :  $codetranche  --> entier repésentant la tranche horaire pour le calcul (de 0 à 23)
						 0 pour de 00h à 01h, 15 pour de 15h à 16h, etc ...
						 
			       $datedebut    --> date de début de l'intervalle (sous la forme 2005-11-16 22:17:12 en chaine de caractères)
			       
			       $datefin      --> date de fin de l'intervalle (sous la forme 2006-07-28 15:01:17 en chaine de caractères)
						 
			       
		retourne    :  le nombre de minutes qu'on a dans la tranche horaire entre les 2 dates
			       
	*/
	
	function getNbMinutes($codetranche, $datedebut, $datefin) 
	{
		$annee_debut   = substr($datedebut,0,4);
		$mois_debut    = substr($datedebut,5,2);
		$jour_debut    = substr($datedebut,8,2);
		$heure_debut   = substr($datedebut,11,2);
		$minute_debut  = substr($datedebut,14,2);
		$seconde_debut = substr($datedebut,17,2);
		
		$annee_fin   = substr($datefin,0,4);
		$mois_fin    = substr($datefin,5,2);
		$jour_fin    = substr($datefin,8,2);
		$heure_fin   = substr($datefin,11,2);
		$minute_fin  = substr($datefin,14,2);
		$seconde_fin = substr($datefin,17,2);
		
		$nb_minutes = 0;
		
		$time_debut = mktime(0, 0, 0, $mois_debut, $jour_debut, $annee_debut);
		$time_fin = mktime(0, 0, 0, $mois_fin, $jour_fin, $annee_fin);
		
		$ecart = $time_fin - $time_debut;
		$nb_jours = floor($ecart / 3600 / 24);
		$nb_jours++;
		
		if ( $nb_jours >= 3 )
		{
			
			$nb_minutes += 60 * ($nb_jours - 2) ;	
			
			
			if ( $heure_debut < $codetranche )
				$nb_minutes += 60;
			
			if ( $heure_debut == $codetranche )
				$nb_minutes += (59 - $minute_debut); 
			
				
			if ( $heure_fin > $codetranche )
				$nb_minutes += 60;
			
			if ( $heure_fin == $codetranche )
				$nb_minutes += $minute_fin; 
			
			
		}
		else
			if ( $nb_jours == 2 )
			{
				
				if ( $heure_debut < $codetranche )
					$nb_minutes += 60;
				
				if ( $heure_debut == $codetranche )
					$nb_minutes += (59 - $minute_debut); 
				
					
				if ( $heure_fin > $codetranche )
					$nb_minutes += 60;
				
				if ( $heure_fin == $codetranche )
					$nb_minutes += $minute_fin; 	
				
					
			}
			else // $nb_jours == 1
			{
			
				if ( ($heure_debut < $codetranche) && ( $heure_fin > $codetranche ) )
					$nb_minutes += 60;
				
				if ( ($heure_debut == $codetranche) && ( $heure_fin > $codetranche ) )
					$nb_minutes += (59 - $minute_debut);
				
				if ( ($heure_debut < $codetranche) && ( $heure_fin == $codetranche ) )
					$nb_minutes += $minute_fin;
				
				if ( ($heure_debut == $codetranche) && ( $heure_fin == $codetranche ) )
					$nb_minutes += ($minute_fin - $minute_debut -1);
				
				
				
				
			}
		
		return $nb_minutes;
		
		      
	}
	
	
	
?>

J'ai testé en long et en large et il marche très bien.

un exemple d'utilisation :

echo "Resultat du calcul : ".getNbMinutes(15, "2005-05-23 18:05:57", "2005-05-28 12:56:11")." minutes";