[SQL] requête qui semble simple mais j'ai du mal...

requête qui semble simple mais j'ai du mal... [SQL] - SQL/NoSQL - Programmation

Marsh Posté le 25-08-2005 à 00:37:53    

Salut,
 
J'ai un probleme que je croyais simple mais après avoir réfléchi 10min, je ne trouve pas la solution.
 
J'ai un simple échantillon
 
A
B
A
A
B
C
D
E
F
F
 
Je veux comme résultat le couple  
(nombre de couples ayant le même nombre d'occurrences de chaque sous élément, taille du couple)  
pour chaque taille de couple différente
 
donc
 
3 => 1 (1 C et 1 D et 1 E)
2 => 2 (2 B et 2 F)
1 => 3 (3 A)
 
Le tout en une requête sans sous requete si possible...  
 
Pour info, c'est pour répondre à une problématique toute simple (sisi ;)).
J'ai dans une table des idvisiteurs, md5
toto
tata
titi
tata
 
et je veux savoir combien de fois chaque visiteur est venu, donc combien de visiteurs sont venus 1 fois, combien 2 fois, combien 3 fois, etc.
 
 
 
Merci d'avance de votre aide !
 
Mat


Message édité par matthieu_phpmv le 25-08-2005 à 00:46:16

---------------
développeur de phpMyVisites mesure d'audience de sites Internet
Reply

Marsh Posté le 25-08-2005 à 00:37:53   

Reply

Marsh Posté le 25-08-2005 à 01:09:10    

En attendant une éventuelle solution au problème, je fais comme ça, donc en N requetes
sachant que N ~ 10-15 cela reste convenable, maispeut mieux faire ;)
 

Code :
  1. $f1 = query("SELECT count(*) as s
  2.      FROM visit
  3.      WHERE idsite = ".$this->site->getId()."
  4.      AND server_date IN (".$inIdArchives." )
  5.      GROUP BY idcookie" );
  6.   while($fx = mysql_fetch_assoc($f1))
  7.   {
  8.    @$res[$fx['s']]++;
  9.   }
  10.   ksort($res);
  11.   printdebug($res);


---------------
développeur de phpMyVisites mesure d'audience de sites Internet
Reply

Marsh Posté le 25-08-2005 à 08:35:26    

Quel SGBD ?
 
S'il accepte les sous-requêtes :
 

Code :
  1. SELECT nombre1, count(*) AS nombre2
  2. FROM (SELECT id, count(*) AS nombre1
  3.       FROM visit
  4.       GROUP BY id)
  5. GROUP BY nombre1;


 
nombre1 = nombre de visites.
nombre2 = nombre de visiteurs par nombre de visites.


Message édité par Beegee le 25-08-2005 à 08:35:45
Reply

Marsh Posté le 25-08-2005 à 12:30:04    

"je veux savoir combien de fois chaque visiteur est venu, donc combien de visiteurs sont venus 1 fois, combien 2 fois, combien 3 fois"
 
Si tu veux répondre juste à cette question, ça revient au même que dire :
 
"je veux savoir combien de fois est venu chaque visiteur"
 
non ?
 
à ce moment, c'est tout bête !
 

Code :
  1. select count(*) nbVisites, idvisiteur
  2. from visites
  3. group by idvisiteurs
  4. order by nbVisites


 
=> Ensuite, dans ton code, tu peux simplement parcourir le résultat, et faire mettons un saut de ligne pour séparrer les listes de visiteurs qui sont venus un certain nombre de fois, genre (en ASP) :
 

Code :
  1. Dim prevNb, openTag
  2. prevNb = 0
  3. openTag = False
  4. Response.Write "<ul>" & vbCrLf
  5. While not rs.EOF
  6.    If rs("nbVisites" ) <> prevNB Then
  7.       prevNb = rs("nbVisites" )
  8.       Response.Write "   <li style=""font-height: bold;"">" & CStr(prevNb) & " visite(s)" & vbCrLf
  9.       openTag = True
  10.       Response.Write "   <ul>" & vbCrLf
  11.    End If
  12.    Response.Write "      <li>" & rs("idvisiteur" ) & "</li>" & vbCrLf
  13.    If openTag Then
  14.       Response.Write "</ul></li>" & vbCrLf
  15.       openTag = False
  16.    End If
  17. loop
  18. Response.Write "</ul>"

Reply

Marsh Posté le 25-08-2005 à 13:35:20    

Beegee effectivement c'est la réponse avec 2 requêtes, on ne peut pas le faire avec une requête je pense.
 
Arjuna, non en fait, je veux pas pour chaque visiteur le nombre de visites, mais bien le nombre de visiteurs qui ont fait N visites, N prenant toutes les valeurs existantes.
 
Je veux  
le nombre de visiteurs ayant fait 1 visite
le nombre de visiteurs ayant fait 2 visites
le nombre de visiteurs ayant fait 3 visites
le nombre de visiteurs ayant fait 4 visites
le nombre de visiteurs ayant fait 5 visites
 
etc.
 
Je ne pense pas qu'il soit possible de le faire en une requête ?


---------------
développeur de phpMyVisites mesure d'audience de sites Internet
Reply

Marsh Posté le 25-08-2005 à 13:55:57    

Je te l'ai mis en une requête plus haut, mais il faut que le SGBD accepte les sous-requêtes.

Reply

Marsh Posté le 25-08-2005 à 13:58:22    

Ben alors tu peux reprendre mon truc, et incrémenter un compteur dans la boucle, et le réinitialiser à chaque changement de prevNb, ça marche aussi.
 
Evidement, ça va te faire un traîtement dans la page, mais ça permet de ne faire qu'une requête simple.

Reply

Marsh Posté le 25-08-2005 à 14:01:51    

En effet, je ne pense pas qu'on puisse faire ça en une seule requête.
 
PS: désolé de pas pouvoir passer plus de temps à faire ton smilblik, j'ai pas mal de trucs à faire en ce moment, genre :
 
Je bosse sur sur un site web écrit en... un mélange de HTML 1,2,3 soleil, avec du code pourri de partout et des JS à réveiller un mort. Je le repasse en XHTML 1.0 Strict avec utilisation abondante de CSS, tout en le rechartant.
 
A côté de ça, faut que je mette en application un mail que j'ai écrit ce matin (comme si la première tâche, 800 pages aussi spécifiques les unes que les autres !) n'était pas suffisante...
 

Citation :


Pour le moment, seul le début du mail (jusqu'au séparateur visuel)
 
Actuellement, on utilise déjà la fonction "Erreur" afin de traîter les éventuelles erreurs retournées par les méthodes ActiveX.
Les ActiveX sont censés gérer leurs propres erreurs, et allimenter une propriété strError.
 
Chaque méthode retourne normalement un booléen, communément appelé "b" lors de la récupération dans l'ASP.
 
Si b = True alors on fait le traîtement
Si b = False alors on traîte l'erreur et on arrête le traîtement
 
Ce code n'est pas généralisée à toutes les pages ni toutes les méthodes. De même, toutes les méthodes ne retournent pas ce booléen.
 
Pour le moment, il faut ajouter, de façon systématique, cette gestion des erreurs :
 
Par exemple :
 
Set obVendeur = server.CreateObject("sInterclass.clszOrganisation" )
b = obVendeur.loadForId(ctx, Request("vendeur" ))
 
On rajoute juste après, lorsque c'est manquant :
 
If Not b Then
    Erreur obVendeur.strError
End If
 
Seul problème, dans le cas où une méthode ne retourne pas de booléen, on a deux options :
-> Contrôler la valeur "bidon" retournée (par exemple, un comptage = -1 devrait indiquer qu'une erreur s'est produite)
-> Modifier la méthode afin qu'elle retourne un booléen (remplacer toutes les Sub par des Function), et allimenter une propriété avec le résultat de la méthode
 
La seconde solution est évidement la meilleure, par contre, dans un souci de rapidité de développement et de restriction des risques d'impact, il vaut mieu qu'on ne touche pas à la valeur de retour. Dans ce cas, au moment de l'appel de la fonction Erreur, ajouter le commentaire, juste au dessus :
 
' Uncharted error
 
Dans le cas où la méthode ActiveX ne traîte pas du tout l'erreur (aucun flag permettant d'identifier une erreur, ou même pas de gestion d'erreur dans la méthode), mettre à la place de la gestion d'erreur ASP le commentaire suivant :
 
' Unmanaged error
 
La présence de ces deux commentaires va nous permettre, dans une seconde passe, plus dédiée à cette gestion des erreurs, d'isoler rapidement les points flaibles de l'application.
 
 
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
 
 
Pour ce qui est de la gestion des erreurs InterClass, la fonction Erreur devra :
-> Récupérer l'objet "error" de la méthode (modifier toutes les classes en conséquence), ainsi qu'une propriété String "methodParams" contenant la liste des paramètres passés à la méthode ainsi que le nom de la méthode appelée, retrouvé sous forme d'une propriété String  "methodName". Si la méthode contient plusieurs points de gestions des erreurs (requêtes consécutives), alors il faudra aussi allimenter une propriété de type Integer au nom de "methodErrorHandlerId" contenant le numéro de la transaction ayant échoué. Une dernière propriété de type String au nom de "methodErrorAddInfo" sera initialisée dans la gestion des erreurs de la méthode contenant des informations à propos des variables locales par exemple (nom la procédure stockée ainsi que ses paramètres, etc.", séparées de la façon suivante : varName=varValue; (format CSV avec cellules nommées).
-> Récupérer l'intégralité des variables :
Request.Form
Request.QueryString
Session
Request.Cookies
Request.ServerVariables
 
-> Loguer toutes ces informations dans une table dédiée dans la base de prod. Si le log dans la base échoue, alors créer un fichier dans un répertoire dédié de l'application contenant les informations.
 
-> Envoyer un mail contenant toutes les informations à une liste de personnes définies dans un paramètre "system.errorHandler.mailTo". Si la récupération de ce paramètre échoue, alors on enverra un mail à une liste d'adresse "en dur" (stockée dans "inc_const.asp" par exemple)
 
-> Rediriger l'utilisateur sur une page d'erreur "propre" (montée sur la base de la page "logout.asp" ) affichant à l'utilisateur qu'une erreur s'est produite, ainsi qu'un numéro de ticket (correspondant à l'ID généré dans la table de log). Eventuellement, on peut aller chercher des informations sur la personne à contacter en cas de problème à partir de la base de données dans un paramètre "system.errorHandler.contact"
 
Attention :
En plus des bugs de programmation, généralement, les erreurs sont levées par des problème sur le serveur (perte de connection avec SQL Server, session expirée, etc.). Il est donc extrêment important que tous les traitements effectués dans cette gestion des erreurs soient correctement échappés, et qu'une action paliative puisse être éxécutée, afin de garder trace de l'erreur (d'où la génération d'un fichier d'erreur sur le disque, ou envoi à une adresse mail en dur).
 
Dans page d'erreur, il ne faut faire rigoureusement AUCUN traîtement ni ActiveX ni utiliser la moindre variable de Session ou autre. Pour cette raison, c'est la fonction "Erreur" qui devra envoyer, par QueryString, les informations à afficher dans la page d'erreur.
La page d'erreur ne peut pas être localisée, toujours pour la même raison. Dans la page de traîtement d'erreur, on pourra checker si la langue de l'utilisateur est reconnaissabe, et, le cas échéant, appeler différentes pages d'erreur, ou choisir d'afficher une page uniquement en français ou en anglais.
 
Eléments de programmation :
 
Dans les Classes VB :
 
Public methodParams As String
Public methodName As String
Public methodErrorHandlerId As Integer
Public methodErrorAddInfo As String
Public errorObject As Variant
 
Exemple de méthode après changement de la gestion d'erreur :
 
Public getNbElementsCount As Long ' This is the old "getNbElements" returned value
 
Function getNbElements(parametre1 As String, parametre2 As Integer, Optional parametre3 As String = "test" ) As Boolean
       ' Copy pointer to object Err in the public property errorObject (then ASP can read VB Error object)
       Set Me.errorObject = Err
 
        Me.methodParams = "parametre1 (String) = " & parametre1 & ";parametre2 (Integer) = " & CStr(parametre2) & ";parametre3 (Optional String) = " & parametre3
        Me.methodName = "getNbElements"
 
        ' Some declarations
 
       On Error GoTo gestError
       Err.Clear ' Empty the error handler to be sure we will raise the correct error
       methodErrorHandlerId = 0
 
       cmd.CommandText = "icsd_doSomethingBeforeCount"
       DelCmdParams cmd
 
       cmd.Parameters.Append cmd.CreateParameter("parametre1", adVarChar, adParamInput, 30, assetid)
       cmd.Parameters.Append cmd.CreateParameter("parametre2", adInteger, adParamInput, , referenceName)
       cmd.Parameters.Append cmd.CreateParameter("parametre3", adVarChar, adParamInput, 30, value)
 
       methodErrorAddInfo = "query=" & cmd.CommandText & ";parametre1=" & parametre1 & ";parametre2=" & CStr(parametre2) & ";parametre3=" & parametre3
       cmd.Execute
 
       Err.Clear ' Empty the error handler to be sure we will raise the correct error
       methodErrorHandlerId = 1
 
       cmd.CommandText = "icsd_doTheCount"
       DelCmdParams cmd
 
       cmd.Parameters.Append cmd.CreateParameter("parametre1", adVarChar, adParamInput, 30, assetid)
 
       methodErrorAddInfo = "query=" & cmd.CommandText & ";parametre1=" & parametre1
       Set rs = cmd.Execute
       Me.getNbElementsCount = rs("count" )
       getNbElements = True
 
       Exit Function
       gestError:
       Me.strError ' (unused as we should send the entire Error Object now)
       getNbElements = False
End Function
 
Dans l'ASP, avant modifs :
 
cpt = myObj.getNbElements("test", 5)
If cpt = 1- Then
     Erreur myObj.strError
End If
 
Dans l'ASP, après modifs :
 
b = myObj.getNbElements("test", 5)
If Not b Then
     ' Now we should send the entire object to the Erreur function !
     Erreur myObj.errorObject, myObj.methodName, myObj.methodParams, myObj.methodErrorHandlerId, myObj.methodErrorAddInfo
End If
cpt = myObj.getNbElementsCount
 
Code pour récupérer la liste de tous les objets "globaux" (à mettre dans le log d'erreur) :
 
Dim el
 
Response.Write "<h1>Request.Form</h1>"
For each el in Request.Form
 Response.Write el & " = " & Request.Form(el) & "<br />"
Next
 
Response.Write "<h1>Request.QueryString</h1>"
For each el in Request.QueryString
 Response.Write el & " = " & Request.QueryString(el) & "<br />"
Next
 
Response.Write "<h1>Request.Cookies</h1>"
For each el in Request.Cookies
 Response.Write el & " = " & Request.Cookies(el) & "<br />"
Next
 
Response.Write "<h1>Session</h1>"
For each el in Session.Contents
 On Error Resume Next
 Response.Write el & " = " & Session(el) & "<br />"
 If Err <> 0 Then
  ' We should try to parse it as a collection or array
  Response.Write "<b style=""color: red;"">" & el & "</b> ne peut pas s'afficher<br />"
 End If
Next
 
Response.Write "<h1>Request.ServerVariables</h1>"
For each el in Request.ServerVariables
 Response.Write el & " = " & Request.ServerVariables(el) & "<br />"
Next
 
 
Voilà, dites-moi ce que vous en pensez, et comment on s'y prend pour la mise en place (la seconde partie du mail demande


 
(sauf que là, je dois faire les deux parties du mail d'un coup... la galère :D)

Reply

Sujets relatifs:

Leave a Replay

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