Page 1 sur 1

Utilisation de TIMESTAMPDIFF (Mysql 5)

Posté : 14 oct. 2006, 15:38
par fiatt
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.

Posté : 14 oct. 2006, 16:06
par Cyrano
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());
}
?>

Posté : 14 oct. 2006, 16:29
par fiatt
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());
} 

Posté : 14 oct. 2006, 17:00
par Cyrano
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 :)

Posté : 14 oct. 2006, 17:11
par fiatt
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!

Posté : 14 oct. 2006, 18:02
par Hubert Roksor
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)

Posté : 14 oct. 2006, 18:43
par fiatt
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.

Posté : 14 oct. 2006, 18:46
par Ajoloca
Bonjour,

et si remplaces UNIX_TIMESTAMP() par CURRENT_TIMESTAMP() ?
SELECT TIMESTAMPDIFF( SECOND, TIMESTAMP('2006-01-01 10:00:00'), CURRENT_TIMESTAMP());

Posté : 14 oct. 2006, 18:58
par fiatt
Bonjour,

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

Posté : 14 oct. 2006, 19:00
par Ajoloca
Ceci fonctionne chez moi

Code : Tout sélectionner

SELECT TIMESTAMPDIFF( SECOND, TIMESTAMP('2006-01-01 10:00:00'), CURRENT_TIMESTAMP());

Posté : 14 oct. 2006, 19:04
par fiatt
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.

Posté : 14 oct. 2006, 19:12
par fiatt
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

Posté : 14 oct. 2006, 19:43
par Hubert Roksor
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).