Page 1 sur 1

comparer 2 chaines de caracteres numeriques: comment?

Posté : 17 oct. 2007, 20:10
par choubix
bonjour,

mes utilisateurs me donnent une chaine de 4 caracteres numeriques. ces chaines sont enregistrees en base de donnees.

ex:
utilisateur 1: 00-11-22-33
utilisateur 2: 44-22-11-77
utilisateur 3: 44-22-77-55
utilisateur 4: 00-99-66-33 (le chanceux! ;) )

je dois comparer leurs chaines de caracteres a MA chaine qui est, par exemple 00-33-66-99
je dois pouvoir lister les utilisateurs avec 1, 2 3 ou tous les bons numeros.

l'ordre importe donc peu.

mes soucis sont de 2 ordres:

- je ne sais pas par ou commencer pour faire ce type de comparaison
- j'ai peur que la requete soit extrement lourde a faire tourner s'il y a pas mal d'utilisateurs...

j'ai bien dans l'idee que je pourrais exploser cette chaine de caracteres en 4 champs puis comparer le champs 1 puis le 2, le 3 et le 4 avec tous les champs de ma chaine de caracteres et cela pour tous les utilisateurs. le truc: l'idee de faire tourner une telle requete me fait deja froid dans le dos s'il y a bcp d'utilisateurs...

est ce que certains ici ou deja eu a faire ce type de tri et qui pourraient me donner un coup de main svp?

merci! :)

Posté : 17 oct. 2007, 22:30
par Berzemus
Est-ce que l'ordre à une importance ?

Sinon, un simple explode pour transformer tes données en en tableau, puis in_array pour vérifier l'existence..

Au fait, y'a une raison pour laquelle ils sont doubles ? sinon y'a moyen de jouer avec levenshtein() (bon, même dans le cas contraire, mais c'est moins fun)..

Posté : 17 oct. 2007, 23:02
par choubix
salut Berzemus,

l'ordre n'a pas dimportance.
le fait que les chiffres soient doubles ne reprente par l'exacte realite par contre (les chiffres vont de 01 a 12 en fait)


je viens de passer sur le descirptif de la fonction leveinstein. je ne suis pas sur que ca me soit utile. par contre maintenant je comprends comment google corrige mes fautes de typo quand je fais une recherche! (bon, ca doit pas etre exactement la meme fonction qd meme ;) )

par contre que dis tu de cette idee:

je recupere les selections des utilisateurs, j'explose le tableau, je tri les chiffres par ordre croissant.
je fais une boucle pour comparer les 2 premiers, puis les 4, puis les 6.... jusqu'a comparer toute la chaine de caractere.

ca m'evite de stocker chaque valeur dans un champs a part comme je le decrivais avant.
par contre la requete va me sembler bien lourde et prendre du temps non?...

qu'en penses tu? aurais tu une meilleure idee ?

Posté : 17 oct. 2007, 23:19
par Hubert Roksor
Pour résumer il s'agit d'un loto c'est bien ça ? Pour commencer, il te faut un schéma SQL qui tient la route :
  1. une table grilles pour enregistrer le bulletin de jeu de chaque joueur, sans oublier le tirage pour lequel le joueur jour,
  2. une table grille_numeros pour enregistrer chaque numéro joué dans chaque grille
  3. une table tirages pour enregistrer les tirages et la date à laquelle ils se sont déroulés
  4. une table tirage_numeros pour enregistrer chaque numéro tiré à chaque tirage
Je ne le précise pas, mais j'imagine que tu as déjà une tables joueurs pour enregistrer tes joueurs. Ce schéma est naturellement extensible, peu importe si un tirage a 4 ou 6 numéros, peu importe si une grille a 4, 5 ou 12 numéros. Il te faudra gérer ces contraintes au niveau de PHP.

Code : Tout sélectionner

CREATE TABLE grilles ( grille_id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, tirage_id mediumint(8) unsigned NOT NULL, joueur_id mediumint(8) unsigned NOT NULL, PRIMARY KEY (grille_id), KEY joueur_id (joueur_id), KEY tirage_id (tirage_id) ); CREATE TABLE grille_numeros ( grille_id mediumint(8) unsigned NOT NULL, numero tinyint(3) unsigned NOT NULL, KEY grille_id (grille_id) ); CREATE TABLE tirages ( tirage_id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, tirage_date date NOT NULL, PRIMARY KEY (tirage_id), KEY tirage_date (tirage_date) ); CREATE TABLE tirage_numeros ( tirage_id mediumint(8) unsigned NOT NULL, numero tinyint(3) unsigned NOT NULL, KEY tirage_id (tirage_id) );
Reste la requête qui calcule le nombre de gagnants pour un tirage donné. Pour cela, on prend la liste des numéros tirés dans tirage_numéros et les grilles jouées dans grilles le tout grâce à tirage_id, et on compte tous les enregistrements dans grille_numeros correspondant à (tirage_id,numero). On groupe le total par grille avec GROUP BY et on ne garde que ceux ayant 3 bons numéros ou plus grâce à HAVING.

Code : Tout sélectionner

SELECT gn.grille_id, COUNT(*) AS cnt FROM (grilles g, tirage_numeros tn) JOIN grille_numeros gn USING (grille_id, numero) WHERE g.tirage_id = 1 AND tn.tirage_id = 1 GROUP BY g.grille_id HAVING cnt >= 3
Résultat : on a la liste des grilles ayant plus de n numéros justes. À toi ensuite de voir à quels joueurs elles correspondent, ou en faire ce que tu veux.

C'est plutôt rapide et ça devrait tenir le coup pour quelques milliers de grilles par tirage.

Pour info, les données que j'ai utlisé pour tester :

Code : Tout sélectionner

INSERT INTO grilles VALUES (1, 1, 1), (2, 1, 2), (3, 1, 3), (4, 1, 4), (5, 1, 2); INSERT INTO grille_numeros VALUES (1, 0), (1, 11), (1, 22), (1, 33), (2, 44), (2, 22), (2, 11), (2, 77), (3, 44), (3, 22), (3, 77), (3, 55), (4, 0), (4, 99), (4, 66), (4, 33), (5, 33), (5, 44), (5, 66), (5, 99); INSERT INTO tirage_numeros VALUES (1, 0), (1, 33), (1, 66), (1, 99);

Posté : 17 oct. 2007, 23:32
par choubix
bonjour hubert et merci du coup de main.

je decortique ca demain premiere heure :)

Posté : 17 oct. 2007, 23:35
par Tracker
J'ai fait quelques tests alors, voilà une autre solution:

Je suis parti avec tes contraintes de structure (vaguement énoncées) et tes infos:

Code : Tout sélectionner

create table paris ( id int not null primary key auto_increment, user_id int not null, -- references user (id) combi char(11) not null ) insert paris (user_id, combi) values (1, '00-11-22-33') insert paris (user_id, combi) values (2, '44-22-11-77') insert paris (user_id, combi) values (3, '44-22-77-55') insert paris (user_id, combi) values (4, '00-99-66-33')

Tu peux récupérer, il me semble, toutes les infos que tu souhaites de l'ordre suivant. la colonne bon_num te donne la liste des bons numéros et nb_bon_num leur nombre par user pour un tirage.

Pour définir le tirage à tester, en php tu transformes ta chaine 00-33-66-99 en '00','33','66','99' pour l'injecter dans le where x.num in ( -><- ).

Code : Tout sélectionner

select id, user_id, group_concat(num order by num) as bon_num, round(length(group_concat(num))*4/11) as nb_bon_num from ( select id, user_id, substring(combi, 1, 2) as num from paris union all select id, user_id, substring(combi, 4, 2) from paris union all select id, user_id, substring(combi, 7, 2) from paris union all select id, user_id, substring(combi, 10, 2) from paris ) x where x.num in ('00','33','66','99') group by id, user_id
Bon c'est une bidouille, mais si ça peut te débloquer..


Tracker.