Faire l'historique d'une table

Faire l'historique d'une table - SQL/NoSQL - Programmation

Marsh Posté le 13-07-2006 à 10:04:56    

Bonjour tous,
Voici ma table:
 
Date Update                   Adr MAC           Wan IP            statut
2006-07-13 09:00:51 00:40:F4:8A00:40:F4:8A:xxxx:xxxx 193.252.xxxxxx  UPDATE
2006-07-12 16:18:10 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-12 14:08:40 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-12 11:00:29 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-11 17:03:30 00:40:F4:8A:xxxx 193.252.xxxxxx UPDATE
2006-07-11 14:49:52 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-11 12:00:06 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-11 09:05:20 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-10 16:13:45 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-10 14:04:37 00:40:F4:8A:xxxx 193.252.xxxxxx BOOT_ON
2006-07-10 14:04:29 00:40:F4:8A:xxxx 193.252.xxxxxx  BOOT_OFF
2006-07-10 09:10:04 00:40:F4:8A:xxxx 193.252.xxxxxx  BOOT_OFF
2006-07-07 16:41:09 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-07 14:29:58 00:40:F4:8A:xxxx 193.252.xxxxxx  BOOT_ON
2006-07-07 14:29:32 00:40:F4:8A:xxxx 193.252.xxxxxx  BOOT_OFF
2006-07-07 11:57:03 00:40:F4:8A:xxxx 193.252.xxxxxx  BOOT_ON
2006-07-07 11:28:13 00:40:F4:8A:xxxx 193.252.xxxxxx  BOOT_OFF
2006-07-06 16:35:09 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-06 14:19:38 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
2006-07-06 11:17:34 00:40:F4:8A:xxxx 193.252.xxxxxx  UPDATE
 
 
Je voudrais obtenir  
Adr Mac                       Wan IP                     Statut           Durée
00:40:F4:8A:xxxx           193.252.xxxxxx           UPDATE        3jours xheures yminutes
 
00:40:F4:8A:xxxx           193.252.xxxxxx           BOOT_ON      xheures yminutes
 
00:40:F4:8A:xxxx           193.252.xxxxxx           BOOT_OFF     4heures yminutes
 
00:40:F4:8A:xxxx           193.252.xxxxxx           UPDATE        2jours xheures yminutes
 
Ainsi de suite.
Donc pour résumer le travail, je souhaite pouvoir comparer chaque ligne du champ statut et calculer la durée si deux lignes consécutives sont identiques.
Je ne suis qu'une pauvre débutante et vos conseils seront la bienvenue.  
J'ajoute que je ne voudrais pas d'un code tout fait mais des pistes ou fonctions pour faire ce travail.
Merci à tous.
 
 

Reply

Marsh Posté le 13-07-2006 à 10:04:56   

Reply

Marsh Posté le 13-07-2006 à 11:21:26    

franchement a premiere vue je ne crois pas que tu puisses eviter de passer par un langage de programmation pour faire cela
 
tu recuperes ton select puis tu fais tes comparaisons / action dessus
En SQL pur ca parait impossible (je peux me tromper bien sur)

Reply

Marsh Posté le 13-07-2006 à 11:22:42    

En fait, il te faut, pour chaque adresse mac et wan ip :
- récupérer les lignes de "début de nouveau statut", càd les lignes telles qu'il n'y a aucune ligne précédente (en ordonnant par date) ou telles que la ligne précédente a un autre statut,
- récupérer la prochaine ligne (toujours en ordonnant par date) qui a un statut différent (la première !), et prendre sa date. S'il n'y en a pas il faut prendre la date système.
 
Ensuite il suffit de faire (date du changement de statut suivant) - (date du changement de statut actuel).
 
edit : betsamee, ça me parait jouable en SQL pur ... un bon gros mélange de NOT EXISTS (x2) avec ORDER BY et GROUP BY à la fin ...

Message cité 2 fois
Message édité par Beegee le 13-07-2006 à 11:23:51
Reply

Marsh Posté le 13-07-2006 à 11:26:32    

C'est jouable en SQL, avec les curseurs.  
 
Quant aux dates, sous Sybase/SQL Server c'est jouable à coup de DATEDIFF, et je pense que les autres SGBD ont des fonctions équivalentes.

Reply

Marsh Posté le 13-07-2006 à 11:26:33    

Beegee a écrit :

En fait, il te faut, pour chaque adresse mac et wan ip :
- récupérer les lignes de "début de nouveau statut", càd les lignes telles qu'il n'y a aucune ligne précédente (en ordonnant par date) ou telles que la ligne précédente a un autre statut,
- récupérer la prochaine ligne (toujours en ordonnant par date) qui a un statut différent (la première !), et prendre sa date. S'il n'y en a pas il faut prendre la date système.
 
Ensuite il suffit de faire (date du changement de statut suivant) - (date du changement de statut actuel).
 
edit : betsamee, ça me parait jouable en SQL pur ... un bon gros mélange de NOT EXISTS (x2) avec ORDER BY et GROUP BY à la fin ...


ok je vois ou tu veux en venir :jap:  
mais a ce niveau la de bidouille je suis deja partisan du code  :D

Message cité 2 fois
Message édité par betsamee le 13-07-2006 à 11:27:08
Reply

Marsh Posté le 13-07-2006 à 11:27:47    

betsamee a écrit :

mais a ce niveau la de bidouille je suis deja partisan du code  :D


 
Je suis d'accord. Un petit script, en PERL par exemple (ce n'est qu'un exemple), permet de réaliser ce genre de chose très facilement, en très peu de temps.

Reply

Marsh Posté le 13-07-2006 à 11:49:47    

OK!
Je vais utiliser le C++ car c'est le langage que je maîtrise le plus.  
Je vous tiens au courant!
Merci pour les indices et bienvenue aux prochains

Reply

Marsh Posté le 13-07-2006 à 14:19:11    

J'y arrive pas!
Personne n'a un début de code à me proposer?  
Finalement je crois bien que j'en ai besoin. Merci pour votre aide.

Reply

Marsh Posté le 13-07-2006 à 14:37:43    

En C++ ce n'est pas simple. En plus ça dépend de l'API utilisée, or tu ne nous as donné aucune information à ce sujet.
 
Pour ce genre de petite tache, un langage de script est quand même plus indiqué je trouve.

Reply

Marsh Posté le 13-07-2006 à 14:45:56    

En PHP est-ce plus aisé?
Merci

Reply

Marsh Posté le 13-07-2006 à 14:45:56   

Reply

Marsh Posté le 13-07-2006 à 14:48:50    

oui clairement

Reply

Marsh Posté le 13-07-2006 à 14:52:16    

Si oui, je peux avoir une esquisse s'il te plaît?
Merci.
Je promets de ne pas recopier bêtement le code mais de le comprendre et de bien l'adapter.
Merci

Reply

Marsh Posté le 13-07-2006 à 14:55:06    

en C# c'est fait en 2 minutes


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 13-07-2006 à 14:57:18    

1) tu ouvres une connection mysql avec mysql_connect();
2) Tu selectionnes une bdd avec mysql_select_db();
3) Tu executes ta requete avec mysql_query();
4) Tu parcoures ton resultat avec mysql_fetch_row(); (par exemple)
     tu fais tes traitements  
5) Tu affiches , mets dans un fichier ton resultat
5) Tu fermes ta connexion avec mysql_close()
 

Reply

Marsh Posté le 13-07-2006 à 14:58:40    

Apparement tout vous semble très simple mais puis-je avoir s'il vous plaît un bout de code ou même d'algo que je vais formaliser?
Merci.

Reply

Marsh Posté le 13-07-2006 à 15:03:11    

on part sur le principe que tu travailles sur le resultat de ta requete ordonnee par ordre croissant sur le champ date.
 
tu prend la ligne courante et la compare avec la ligne precedente (que tu auras au prealable copiee dans un array) , si les statuts sont les memes tu calcules ta duree et l'ajoute a la precedente , si ils sont differents tu stockes l'ancienne duree avec le statut et les champs ip de la ligne precedente , tu remets ta duree a 0 ...


Message édité par betsamee le 13-07-2006 à 15:04:17
Reply

Marsh Posté le 13-07-2006 à 15:03:38    

non, on ne fait pas les devoirs des autres. Poste ton code et on te dira ce qui ne va pas.


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 13-07-2006 à 15:04:12    

Ok! A tout de suite

Reply

Marsh Posté le 13-07-2006 à 15:36:14    

vinoromano a écrit :

Ok! A tout de suite


 
Ma table est Tserveur et je veux obtenir Tsrv_Opt.
 
Voici mon code. Le problème est au niveau de l'indice i, i+1 car je ne sais comment l'utiliser.
 
Merci pour votre aide.
 

Code :
  1. <?
  2. if(empty($_REQUEST["Mac"])){      $Mac = "";             }
  3. else            {    $Mac = $_REQUEST["Mac"];     }
  4. function historique($Mac)
  5. {
  6.    $time=0;
  7.    $sql_table=sprintf("SELECT * FROM Tserveur WHERE Mac='%s' ORDER BY Heure DESC", $Mac);//on obtient la table postée en début
  8.  $result_table=mysql_query($sql_table) or die('Erreur SQL !'.$sql.'<br>'.mysql_error());
  9.  $num_rows=mysql_num_rows($result_table);
  10.  for($i=0;$i<$num_rows;$i++)
  11.  {
  12.     while($row_table=mysql_fetch_array($result_table))
  13.   {
  14.      if(strcmp($row_table['Etat_Serv'](i) , $row_table['Etat_Serv'](i+1))==0)
  15.     {
  16.        $time=$row_table['Date Update'](i)+$row_table['Date Update'](i+1);
  17.      $sql_table1=sprintf("INSERT INTO Tsrv_Opt(Adr Mac, Wan IP, Statut, Duree) VALUES (Tserveur.Mac,Tserveur.Adr,Tserveur.IP,$time)" );
  18.      $result_table1=mysql_query($sql_table1);
  19.     }
  20.     else
  21.     {
  22.      $sql_table2=sprintf("INSERT INTO Tsrv_Opt(Adr Mac, Wan IP, Statut, Duree) VALUES (Tserveur.Mac,Tserveur.Adr,Tserveur.IP,Date Update)" );
  23.      $result_table2=mysql_query($sql_table2);
  24.     }
  25.   }
  26.  }
  27. }     
  28. ?>


Reply

Marsh Posté le 13-07-2006 à 15:37:27    

Je rappelle que c'est du PHP.
Merci.

Reply

Marsh Posté le 13-07-2006 à 16:08:48    

Toujours personne pour m'aider?
J'ai posté le code comme je le pense et mon problème réside en l'utilisation des indices i, i+1.
Merci

Reply

Marsh Posté le 13-07-2006 à 16:29:41    

"$row_table=mysql_fetch_array($result_table)"
A chaque fois qu'on utilise "mysql_fetch_array", cette fonction retourne une et une seule ligne de résultat SQL par demande (et non pas une colonne comme tu l'écris dans ton algo) et déplace le pointeur sur la ligne suivante (ce qui fait que l'appel suivant lira la ligne suivante). Le tableau retourné par cette fonction contient une case par colone retourné par la requette.
Pour plus d'infos voir : http://fr2.php.net/manual/fr/funct [...] -array.php
 
 
Côté algo, vu qu'on n'a pas encore lu la ligne suivante, il est difficile de comparer la ligne actuelle avec la ligne suivante. Par contre, à partir de la seconde ligne, il sera possible de comparer la ligne actuelle à la ligne précédante à partir du moment où on a pris soin de copier les données de la ligne précédante dans une autre variable.
 
 
A noter aussi que si tu dois faire les comparaisons adresse Ip par adresse Ip, il faudra trié le résultat de la requette sur l'ip en majeur et l'heure en mineur ("order by Ip,heure" ) et tenir compte du changement d'Ip dans ton algo.
 
 
PS : La ligne "while($row_table=mysql_fetch_array($result_table))" va avoir lu toutes les lignes retourné par la requette. Ce n'est donc pas nécessaire de rajouter une autre boucle autour pour arriver à ça. ;)


Message édité par omega2 le 13-07-2006 à 16:32:48
Reply

Marsh Posté le 13-07-2006 à 16:40:35    

Avant tout merci!
Je vais relire tout ça et faire les corrections puis poster.
Merci.

Reply

Marsh Posté le 17-07-2006 à 10:37:06    

Bonjour tous,
Comment comparer deux lignes successives d'un champ d'une table sql?
Merci

Reply

Marsh Posté le 17-07-2006 à 10:42:11    

En mémorisant la ligne précédente pour comparer avec la ligne courante.

Reply

Marsh Posté le 17-07-2006 à 10:54:21    

Elmoricq a écrit :

En mémorisant la ligne précédente pour comparer avec la ligne courante.


Donc si je fais par exemple:
 

Code :
  1. while(row9 = mysql_fetch_array(result9))
  2.   {
  3.     valeur = sprintf("%s",row9[Etat_Serv]); //copie de la premiere ligne du champ Etat_Serv
  4.     heure = sprintf("%s",row9[DateUpdate]); //copie de la premiere ligne du champ DateUpdate
  5.     if(strcmp(valeur,row9[Etat_serv])==0)  //Comparaison de la 1ere ligne avec la 2nde du meme champ
  6.     {
  7.       duree = heure + row9[DateUpdate];  //addition de la duree
  8.     }
  9.     else
  10.     {
  11.       duree = row9[DateUpdate];
  12.     }
  13.   }


En langage C++

Reply

Marsh Posté le 17-07-2006 à 10:56:44    

Tel que tu l'as écrite, ta condition sera toujours vraie.

Reply

Marsh Posté le 17-07-2006 à 11:03:08    

Donc, c'est juste alors!
En résumé, dès que je fais la copie du contenu de la ligne row9 dans une variable, un nouvel appel de row9 passe directement à la ligne suivante?
 

Reply

Marsh Posté le 17-07-2006 à 11:18:05    

Non, ce n'est pas juste.
Dans ton code, tu initialises "valeur" avec "row9[Etat_Serv]", et tu testes ensuite si les deux valeurs sont égales. Ce qui est toujours vrai (ou alors tu as de gros soucis sur ta machine.)
 
Tu passes à la ligne suivante à chaque mysql_fetch_array()


Message édité par Elmoricq le 17-07-2006 à 11:18:46
Reply

Marsh Posté le 17-07-2006 à 11:30:09    

OK donc il faut que je revois ma boucle while!
Merci.

Reply

Marsh Posté le 17-07-2006 à 11:34:02    

Une question vitale,
Comment faire donc pour recopier la valeur de row9 dans une variable puis comparer cette valeur avec la valeur suivante de row9?
Si je fais une boucle for avec un décompte des lignes comment faire pour utiliser les indices?
Merci de votre aide

Reply

Marsh Posté le 17-07-2006 à 11:40:16    

il faut utiliser des GoTo, c'est la preuve d'un code imaginatif et moderne.


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 17-07-2006 à 11:43:57    

Le plus simple est d'initialiser "valeur" et "heure" avant la boucle, sur le premier résultat de mysql_fetch_array()
 
Ensuite, tu lances ton while comme tu fais ici, tu testes directement "valeur" et "heure" avec le résultat stocké dans row9 (donc tu testes bien la ligne 1 avec la ligne 2), et juste avant la fin de la boucle, tu ré-initialises "valeur" et "heure" avec le row9 courant.
Comme ça, rebelotte au début de la boucle, row9 représente la 3e ligne, "valeur" et "heure" sont des sauvegardes de la ligne précédente. Et ainsi de suite jusqu'à la fin.
 
Il faut penser en terme d'algorithme avant de coder directement, en fait :

Chercher la première ligne de résultats
Mémoriser les résultats de la 1e ligne
 
TANT QUE il reste des résultats
   Chercher la ligne suivante de résultats
   SI valeur mémorisée == valeur courante
   ALORS
      ...
   SINON
      ...
   FIN SI
 
   Mémoriser la ligne courante
FIN TANT QUE

Reply

Marsh Posté le 17-07-2006 à 11:44:04    

Tamahome a écrit :

il faut utiliser des GoTo, c'est la preuve d'un code imaginatif et moderne.


 C'est quoi les GoTo?
Et ce code qu'en pensez-vous?

Code :
  1. result9 = mysql_store_result(&mysql);
  2. int nombre = mysql_num_rows(result9); //nombre de lignes du resultat de mysql_query
  3. for(i=0;i<nombre;i++)
  4. {
  5.   row9 = mysql_fetch_array(result9);
  6.   valeur = sprintf("%s",row9[Etat_Serv]);
  7.   heure = sprintf("%s",row9[DateUpdate]);
  8.   row9 = mysql_fetch_array(result9);
  9.   if(strcmp(valeur,row9[Etat_serv])==0)
  10.   {
  11.     duree = heure + row9[DateUpdate];
  12.   }
  13.   else
  14.   {
  15.     duree = row9[DateUpdate];
  16.   }
  17. }


Merci

Reply

Marsh Posté le 17-07-2006 à 11:49:05    

Elmoricq a écrit :

Le plus simple est d'initialiser "valeur" et "heure" avant la boucle, sur le premier résultat de mysql_fetch_array()
 
Ensuite, tu lances ton while comme tu fais ici, tu testes directement "valeur" et "heure" avec le résultat stocké dans row9 (donc tu testes bien la ligne 1 avec la ligne 2), et juste avant la fin de la boucle, tu ré-initialises "valeur" et "heure" avec le row9 courant.
Comme ça, rebelotte au début de la boucle, row9 représente la 3e ligne, "valeur" et "heure" sont des sauvegardes de la ligne précédente. Et ainsi de suite jusqu'à la fin.
 
Il faut penser en terme d'algorithme avant de coder directement, en fait :

Chercher la première ligne de résultats
Mémoriser les résultats de la 1e ligne
 
TANT QUE il reste des résultats
   Chercher la ligne suivante de résultats
   SI valeur mémorisée == valeur courante
   ALORS
      ...
   SINON
      ...
   FIN SI
 
   Mémoriser la ligne courante
FIN TANT QUE



 
Donc ce code devrait aller?
Merci pour l'explication.  
 

Code :
  1. result9 = mysql_store_result(&mysql);
  2. int nombre = mysql_num_rows(result9); //nombre de lignes du resultat de mysql_query
  3. if(nombre>0)
  4. {
  5.   row9 = mysql_fetch_array(result9);
  6.   valeur = sprintf("%s",row9[Etat_Serv]);
  7.   heure = sprintf("%s",row9[DateUpdate]);
  8.   while(row9 = mysql_fetch_array(result9))
  9.   {
  10.     if(strcmp(valeur,row9[Etat_serv])==0)
  11.     {
  12.       duree = heure + row9[DateUpdate];
  13.     }
  14.     else
  15.     {
  16.       duree = row9[DateUpdate];
  17.     }
  18.     valeur = sprintf("%s",row9[Etat_Serv]);
  19.     heure = sprintf("%s",row9[DateUpdate]);
  20.   }
  21. }

Reply

Marsh Posté le 17-07-2006 à 14:15:19    

Quelqu'un pourrait il me dire si c'est correct ce code?
Aussi pour calculer le temps passé entre deux dates de la forme 2006-05-04 10:25:58, faut il obligatoirement le convertir en secondes avant de faire la différence?
Merci

Reply

Marsh Posté le 18-07-2006 à 09:07:59    

Bonjour,
y a-t-il quelqu'un à l'autre bout pour m'aider?
Merci.

Reply

Marsh Posté le 18-07-2006 à 11:41:13    

Je l'ai fait en PHP mais je souhaite que quelqu'un daigne me le corriger si possible.
Merci de me faire signe


---------------
Merci
Reply

Marsh Posté le 18-07-2006 à 13:16:29    

euh je suis pas un pro du php mais pourquoi y'a des row9 en dehors du while ?


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 18-07-2006 à 13:56:24    

en fait je mets les valeurs des champs de la premiere ligne qui m'intéresse dans une variable afin de les comparer avec la deuxieme c'est pour cela row9 avant le while.
Moi aussi je débute c'est pourquoi je demande de corrections avis ou autres
Merci


---------------
Merci
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed