Utilisation de TIMESTAMPDIFF (Mysql 5)

Eléphanteau du PHP | 28 Messages

14 oct. 2006, 15:38

J'essaye de calculer le nombre de secondes entre deux dates.
A cette fin j'utilise la nouvelle fonction TIMESTAMPDIFF de la version 5 de Mysql:

TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)
Retourne la différence entière entre les expressions datetime_expr1 et datetime_expr2 , de format DATE et DATETIME . L'unité du résultat est donné par l'argument interval . Les valeurs légales de interval sont les mêmes que pour la fonction TIMESTAMPADD() .


mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');
-> 3
mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');
-> -1


Voici mon code:
$query = mysql_query ("SELECT date_dernier_calcul FROM stock WHERE id_machines='1'") or die(mysql_error()); 
while ($dernier_calcul = mysql_fetch_row($query))
{
$time = mysql_query("UPDATE stock SET nombre_secondes = TIMESTAMPDIFF(SEC,'" . DATE(Y-M-D H:i:s) . "','" . $dernier_calcul[0] ."')") or die(mysql_error());
}
Première question: est-il possible de retirer la boucle? cad je mets le pointeur sur un champs précis (une seule donnée) mais je ne sais pas comment faire pour utiliser cette donnée sans mysql_fetch_array.

Deuxième question: j'ai la traditionnelle Parse error: parse error, unexpected T_STRING dans la ligne qui commence par $time mais je ne trouve pas l'erreur...

Merci de votre aide.

Mammouth du PHP | 19672 Messages

14 oct. 2006, 16:06

Les problèmes de concaténation et de mélange de PHP, de SQL et de chaine de caractère, ça peut créer des surprises.

Corrigé, note bien dans la seconde requête, j,ai ajouté un détail que tu devrais regarder de près pour ne pas mettre toute une table à jour au lieu de ne mettre qu'une seule ligne à jour.
<?php
$sql1 = "SELECT date_dernier_calcul ".
        "FROM stock ".
        "WHERE id_machines='1'";
$query = mysql_query ($sql1) or die(mysql_error());
while ($dernier_calcul = mysql_fetch_row($query))
{
    $sql2 = "UPDATE stock ".
            "SET nombre_secondes = TIMESTAMPDIFF(SEC, '". date("Y-M-D H:i:s") ."', '". $dernier_calcul[0] ."') ".
            "WHERE ??? = ???";
    $time = mysql_query($sql2) or die(mysql_error());
}
?>
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphanteau du PHP | 28 Messages

14 oct. 2006, 16:29

Merci Cyrano pour le "where" qu j'avais oublié!

Voici maintenant l'erreur que j'ai:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SEC, '2006-10-14 16:23:48', '2006-10-14 13:49:43')' at line 1

Tout ce que j'ai fait c'est copier-coller le code et modifier le D en d et le M en m dans DATE() afin d'avoir le bon format.

Je précise que le serveur de la BDD est en version Mysql 5.0.
$sql1 = "SELECT date_dernier_calcul ".
        "FROM stock ".
        "WHERE id_machines='1'";
$query = mysql_query ($sql1) or die(mysql_error());
while ($dernier_calcul = mysql_fetch_row($query))
{
    $sql2 = "UPDATE stock ".
            "SET nombre_secondes = TIMESTAMPDIFF(SEC, '". date("Y-m-d H:i:s") ."', '". $dernier_calcul[0] ."') ".
            "WHERE id_machines = '1'";
    $time = mysql_query($sql2) or die(mysql_error());
} 

Mammouth du PHP | 19672 Messages

14 oct. 2006, 17:00

Fais donc un truc juste avant l'exécution dans la boucle : echo("<code>". $sql2 ."</code>\n");

Affiche moi le résultat ici si tu ne trouves pas l'erreur toi-même :)
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphanteau du PHP | 28 Messages

14 oct. 2006, 17:11

En fait il ne faut pas mettre SEC mais SECOND lol mais le résultat donne 0 alors je change de tactique ;)

j'ai réussi à faire ce que je voulais d'une autre manière:
$sql1 = "SELECT date_dernier_calcul ".
        "FROM stock ".
        "WHERE id_machines='1'";
$query = mysql_query ($sql1) or die(mysql_error());
while ($dernier_calcul = mysql_fetch_row($query))
{
$sql2 = "UPDATE stock ".
        "SET nombre_secondes = (UNIX_TIMESTAMP('" . DATE("Y-m-d H:i:s") . "') - UNIX_TIMESTAMP('" . $dernier_calcul[0] ."')),".
		" date_dernier_calcul = NOW()" .
		"WHERE id_machines = '1'";
$time = mysql_query($sql2) or die(mysql_error());
} 
En faisant cela j'ai le bon nombre de secondes entre les deux calculs et la date de dernier calcul est correctment mise à jour.
Merci de ton aide!

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

14 oct. 2006, 18:02

Peut-être me trompe-je, mais ce script ne pourrait-il pas être remplacé par cette requête ?

Code : Tout sélectionner

UPDATE stock SET nombre_secondes = TIMESTAMPDIFF(SECOND, UNIX_TIMESTAMP(), date_dernier_calcul), date_dernier_calcul = NOW() WHERE id_machines = 1
Quelques idées/commentaires:
  • UNIX_TIMESTAMP(NOW()) peut être remplacé par UNIX_TIMESTAMP()
  • attention à ne pas mélanger l'heure de MySQL et l'heure de PHP, elles peuvent être différentes ! donc soit tu utilises UNIX_TIMESTAMP() et NOW() en MySQL, soit time() et date('Y-m-d H:i:s') en PHP
  • en règle générale, si tu as une requête dans une boucle c'est qu'il y a un problème. Les UPDATE peuvent travailler directement sur les valeurs en base. (et dans le cas des SELECT, on peut généralement remplacer un SELECT dans une boucle par une jointure)

Eléphanteau du PHP | 28 Messages

14 oct. 2006, 18:43

J'ai testé la solution de Hubert Roksor:
$sql = "UPDATE stock ".
"SET nombre_secondes = TIMESTAMPDIFF(SECOND, UNIX_TIMESTAMP(), date_dernier_calcul),". 
"date_dernier_calcul = NOW() ".
 "WHERE id_machines = '1'";
 
 $result = mysql_query($sql);
Cela fonctionne au niveau de la mise à jour du champ date_dernier_calcul mais le champ nombre_seconde reste à NULL ou à la valeur par défaut si NULL interdit.

J'ai essayé cette requête manuelle:

Code : Tout sélectionner

SELECT TIMESTAMPDIFF( SECOND, UNIX_TIMESTAMP(), UNIX_TIMESTAMP('2006-01-01 10:00:00'));
Mysql me retourne NULL... je ne comprend pas pourquoi.

ViPHP
ViPHP | 1961 Messages

14 oct. 2006, 18:46

Bonjour,

et si remplaces UNIX_TIMESTAMP() par CURRENT_TIMESTAMP() ?
SELECT TIMESTAMPDIFF( SECOND, TIMESTAMP('2006-01-01 10:00:00'), CURRENT_TIMESTAMP());
Modifié en dernier par Ajoloca le 14 oct. 2006, 18:59, modifié 1 fois.
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

Eléphanteau du PHP | 28 Messages

14 oct. 2006, 18:58

Bonjour,

et si remplaces UNIX_TIMESTAMP() par CURRENT_TIMESTAMP() ?
Idem

ViPHP
ViPHP | 1961 Messages

14 oct. 2006, 19:00

Ceci fonctionne chez moi

Code : Tout sélectionner

SELECT TIMESTAMPDIFF( SECOND, TIMESTAMP('2006-01-01 10:00:00'), CURRENT_TIMESTAMP());
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

Eléphanteau du PHP | 28 Messages

14 oct. 2006, 19:04

Ceci fonctionne chez moi

Code : Tout sélectionner

SELECT TIMESTAMPDIFF( SECOND, TIMESTAMP('2006-01-01 10:00:00'), CURRENT_TIMESTAMP());
Oui chez moi aussi. Il me semblais que c'était expr1 - expr2 et pas le contraire pourtant.

Eléphanteau du PHP | 28 Messages

14 oct. 2006, 19:12

ok maintenant je crois que c'est bon.

Voici le code:
$sql = "UPDATE stock ".
"SET nombre_secondes = TIMESTAMPDIFF( SECOND, TIMESTAMP(date_dernier_calcul), CURRENT_TIMESTAMP()) , ".
"date_dernier_calcul = NOW()". 
 "WHERE id_machines = '1'";
 
 $result = mysql_query($sql);
Il ne me reste plus qu'à l'appliquer à toutes mes données!

Merci à tous de votre aide et à bientôt pour une autre question!! :D

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

14 oct. 2006, 19:43

Oops, désolé. En effet, UNIX_TIMESTAMP() renvoit un nombre (de secondes) alors que TIMESTAMP_DIFF() a besoin d'un timestamp (une chaîne de caractères, donc).