Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2585 connectés 

  FORUM HardWare.fr
  Programmation
  PHP

  [SQL] Une requete bien compliquée

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[SQL] Une requete bien compliquée

n°2017324
nisalon_ca​je
Posté le 17-08-2010 à 00:02:40  profilanswer
 

Bonsoir,
 
Je travaille en php avec mysql, et j'ai besoin de faire une requete que je n'arrive pas à formaliser algorithmiquement
 
J'explique mon problème.
Dans ma table j'ai notamment 5 colonnes, que l'on appellera C1, ... C5 (et qui sont telles que les pour une ligne donnée, la valeur dans la colonne 1 est inférieure ou égale à celle de la colonne 2, elle même inférieure ou égale à la valeur de la colonne 3 et ainsi de suite...) .
J'ai aussi une colonne id (les ids de chacun des enregistrements sont tous différents) (je ne sais pas si ca peut vous servir par la suite, mais je précise tout de meme que je dispose de cette colonne id)
 
J'ai un nombre de variables k compris entre 1 et 5 (on va dire qu'elles sont triées de manière croissante, si ca peut aider...)
 
Ce que je veux faire, c'est déterminer les lignes pour lesquelles on trouve les valeurs de toutes les variables dans les colonnes C1 à C5.
Mais attention, si deux de mes variables ont la même valeur, pour qu'une ligne soit sélectionnée, il faut que la valeur apparaisse deux fois.
 
 
Je ne sais pas si j'ai été très clair, je vais donc faire un petit exemple
 
 
Disons que j'ai k=3
$v1=1
$v2=3
$v3=4
 
C1 -- C2 -- C3 -- C4 -- C5
 0       1      3       4      5   -> OK
 0       2      3       4      5  -> Pas OK (le 1 n'est dans aucune des colonnes)
 
 
Maintenant si j'ai  
$v1=1
$v2=3
$v3=3
 
C1 -- C2 -- C3 -- C4 -- C5
 0       1      3       4      5   -> Pas ok, j'ai deux variables à 3, il faut donc au moins deux apparitions de "3" dans mes colonnes (et les autres variables doivent apparaitre également)
 0       1      2       3      3   -> OK
 0       1      3       3      3   -> OK
 
 
 
 
Dans un premier temps, je pensais faire quelque chose comme ca

Code :
  1. "... WHERE (C1=$v1 OR C2=$v1 OR C3=$v1 OR C4=$v1 OR C5=$v1) AND (C1=$v2 OR C2=$v2 OR C3=$v2 OR C4=$v2 OR C5=$v2) AND (C1=$v3 OR C2=$v3 OR C3=$v3 OR C4=$v3 OR C5=$v3)


 
Le problème, c'est que ca fait un gros paquet de conditions (et je sais pas trop si sql va apprécié); mais surtout que dans le cas ou deux variables sont égales, et bien la requête ne fonctionne pas correctement.
 
 
J'aurais donc besoin de votre aide, parce que ca fait un petit bout de temps que je suis là dessus, et à vrai dire, je sèche :(
 
Merci d'avance :)


Message édité par nisalon_caje le 17-08-2010 à 00:04:50
mood
Publicité
Posté le 17-08-2010 à 00:02:40  profilanswer
 

n°2017329
flo850
moi je
Posté le 17-08-2010 à 01:39:12  profilanswer
 

je pense que tu prends le problème à l'envers  
 
un truc comme ça ne marcherai t il pas ?  
 
WHERE $v1 IN (c1,c2,c3,c4,c5) AND $v2 IN (c1,c2,c3,c4,c5) AND $v3 IN (c1,c2,c3,c4,c5)
 
vu que c'est classé, tu peux optimiser un peu ( toujours pas bien sur, il est tard )
 
WHERE $v1 IN (c1,c2,c3) AND $v2 IN (c2,c3,c4) AND $v3 IN (c3,c4,c5)

n°2017330
Profil sup​primé
Posté le 17-08-2010 à 01:46:50  answer
 

salut,
 
tu n'as pas précisé si tu voulais faire cela entièrement en sql ou bien via php
 
voilà un début de solution (un p'tit temps libre :) ):
 

Code :
  1. <?php
  2. //définition des valeur à trouver
  3. $variables = array(1,3,3);
  4. //récuperes ici tes champs C1 à C5 pour tel ID
  5. $bdd = array(3,1,5,2,3);
  6. //comptabilisation des valeurs par fréquence d'apparition
  7. $bddfield_by_values = array_count_values($bdd);
  8. //on ne récupère que la fréquence pour les valeurs que tu as spécifié dans $variables
  9. $only_variables = array_intersect_key($bddfield_by_values,array_flip($variables));
  10. var_dump($only_variables);
  11. ?>


il est désormais simple, pour chacune de tes valeurs, de savoir si le nombre d'apparitions est >= à ce que tu souhaites


Message édité par Profil supprimé le 17-08-2010 à 01:48:09
n°2017368
nisalon_ca​je
Posté le 17-08-2010 à 10:48:29  profilanswer
 

@flo -> ton truc ne marchera pas, puisque si par exemple j'ai v1=2 v2=2 v3=2 et
 
c1=1 c2=2 c3=3 c4=4 c5=5, ta requete sortira cette ligne là alors que le 2 n'apparait qu'une seule fois
 
 
@spike, cela fonctionne :)
Le seul problème avec ta méthode, est le fait que si ma table fait 100 000 enregistrements, j'ai peur que ce soit un peu long en traitement :(
En fait je comptais le faire plutôt dans une requete sql pour pouvoir placer des index derrière pour essayer d'accélérer le tout ...
Mais bon ta solution marche très bien !


---------------
http://nisalon.labrute.com/
n°2017398
nisalon_ca​je
Posté le 17-08-2010 à 12:39:19  profilanswer
 

J'ai trouvé une solution qui fonctionne, mais qui n'est pas très jolie, en repartant du IN de flo850 :

 
Code :
  1. $k=count($variables);
  2. switch($k){
  3. case 0:
  4. $conditions="";
  5. break;
  6. case 1:
  7. $conditions="$variables[0] IN (C1,C2,C3,C4,C5)"
  8. break;
  9. case 2:
  10. $conditions="($variables[0],$variables[1]) IN ((C1,C2),(C1,C3),(C1,C4),(C1,C5),(C2,C3),(C2,C4),(C2,C5),(C3,C4),(C3,C5),(C4,C5))";
  11. break;
  12. case 3:
  13. $conditions="($variables[0],$variables[1],$variables[2]) IN ((C1,C2,C3),(C1,C2,C4),(C1,C2,C5),(C1,C3,C4),(C1,C3,C5),(C1,C4,C5),(C2,C3,C4),(C2,C3,C5),(C2,C4,C5),(C3,C4,C5))";
  14. break;
  15. case 4:
  16. $conditions="($variables[0],$variables[1],$variables[2],$variables[3]) IN ((C1,C2,C3,C4),(C1,C2,C3,C5),(C1,C2,C4,C5),(C1,C3,C4,C5),(C2,C3,C4,C5))";
  17. break;
  18. case 5:
  19. $conditions="$variables[0]=C1 AND $variables[1]=C2 AND $variables[2]=C3 AND $variables[3]=C4 AND $variables[4]=C5";
  20. break;
  21. }
  22. $sql="SELECT ... WHERE $conditions";
 

C'est pas super joli, mais j'ai l'avantage que je peux facilement utiliser d'autres instructions telles limit, group by etc etc

 


Si quelqu'un sait comment optimiser ça, je suis preneur :) (d'autant plus qu'un explain indique la non prise en compte des index, meme si l'on crée un index sur chaque colonne, sur chaque couple de colonne, sur chaque triplet de colonnes ...)


Message édité par nisalon_caje le 17-08-2010 à 12:48:22

---------------
http://nisalon.labrute.com/
n°2017524
Profil sup​primé
Posté le 17-08-2010 à 22:56:35  answer
 

oh my god!  Vu l'heure ou j'avais rédigé mon idée, j'ai pas percuté que t'avais un ordre croissant dans tes colonnes C1->C5
 
en fait tu peux le faire avec une simple requete sql :
 
soit tes chiffres 1 3 3 :  
 
cela te renvoi les lignes contenant forcément 1 3 3, meme si un "2" se loge entre, et basta :
 

Code :
  1. SELECT id, concat( C1,  '-', C2,  '-', C3,  '-', C4,  '-', C5 )  AS myconcat
  2. FROM  `test`
  3. GROUP  BY id
  4. HAVING myconcat LIKE  '%1%3%3%'


si par contre, les valeurs recherchés doivent apparaitre forcément à la suite, tu peux remplacer par cela, peut etre moins lourd :

Code :
  1. SELECT ...
  2. HAVING myconcat LIKE '%1-3-3%'


what else?
et on se fiche du nombre de variables à checker, t'as juste ta chaine à construire


Message édité par Profil supprimé le 17-08-2010 à 22:57:58
n°2017526
nisalon_ca​je
Posté le 17-08-2010 à 23:11:28  profilanswer
 

merci spike :)


Message édité par nisalon_caje le 17-08-2010 à 23:55:40

---------------
http://nisalon.labrute.com/
n°2017530
nisalon_ca​je
Posté le 17-08-2010 à 23:57:36  profilanswer
 

Oula ca me semblait bon, mais en fait nan :(

 

C1 C2  C3  C4  C5
 1  31  32  45  66

 

La requête remonte la ligne alors qu'elle n'est pas correcte.
je regarde si rajouter des tirets avant les % ne pourrait pas nous aider

 

Edit : si on faisait par exemple ...

Code :
  1. SELECT ...
  2. HAVING myconcat LIKE  '%1-%3-%3-%'

, avoir
C1 C2  C3  C4  C5
 1  13  23 45  66

 

serait correct, alors que ca ne l'est pas

 

et si on mets un tiret avant, un tiret apres,

Code :
  1. SELECT ...
  2. HAVING myconcat LIKE  '%-1-%-3-%-3-%'

, et ben ca marche pas non plus, puisqu'on se retrouve potentiellement avec 1--3 (alors qu'on ne met jamais de -- dans notre concat) et au début c'est galère

 

Apparemment, il faut faire un

Code :
  1. concat( '-',C1,  '--', C2,  '--', C3,  '--', C4,  '--', C5 ,'-')
 

et pour générer la chaine à rechercher :

Code :
  1. %-$variables[0]-%-$variables[1]-%-$variables[2]-%-...-%-$variables[k]-%


Message édité par nisalon_caje le 18-08-2010 à 00:08:15

---------------
http://nisalon.labrute.com/
n°2017538
Profil sup​primé
Posté le 18-08-2010 à 01:13:22  answer
 

normal, t'avais pas précisé que les valeurs pouvaient être des nombres sur deux chiffres, alternative bien trouvée


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  PHP

  [SQL] Une requete bien compliquée

 

Sujets relatifs
[RESOLU] Requête SQL avec traitement d'un champ date[SQL Server] Job et espace dans le nom de la BDD
[RESOLU]Stocker le résultat d'une requête dans un tableauProblème de requête sql
Pour les pros du SQL (prb avec récursivité)[PL/SQL] ORA-01403: Aucune donnée trouvée
Heure SQL SQL server management studio 2005 & plan de maintenance
Requête résultat aléatoire 
Plus de sujets relatifs à : [SQL] Une requete bien compliquée


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR