Organisation de ma (mes) tables ??

Eléphant du PHP | 89 Messages

11 mars 2005, 18:11

Bonjour,

j'ai posté ce problème dans la rubrique débuter en php, mais je pense qu'il a aussi sa place dans cette rubrique.

Quelqu'un peut-il jeter un coup d'oeil à la fin du post à http://www.phpfrance.com/forums/voir_sujet-816.php

et éventuellement m'aider ?

D'avance merci.

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

14 mars 2005, 12:38

Votre message d'origine est :
Bon, j'ai suivi vos conseils. J'ai créé la table tirage_tbl suivante:

dtirage num1 num2 num3 num4 num5 num6 numérocompl

23/2/01 1 2 3 12 14 10 11
22/2/00 7 25 28 30 40 41 38
..... ......

Imaginons que je demande combien de fois mes n° 1,2,3,4,5,6 et le complémentaire le 7 sont sortis:

J'ai regardé la doc sur les fonctions agrégats:

select dtirage count (num1,num2,num3,num4,num5,num6,numérocompl) from tirage_tbl
where (1,2,3,4,5,6) in num1 or (1,2,3,4,5,6) in num2 or (1,2,3,4,5,6) in num3 or (1,2,3,4,5,6) in num4 or (1,2,3,4,5,6) in num5 or (1,2,3,4,5,6) in num6
and numérocompl = 7
and count() > 3
goup by dtirage;

La requête devrait me ramener 3 bons numéros le 23/2/01, mais ce n'est pas du tout le cas :cry:

Quelqu'un peut-il m'aider ?
En fait, la structure de la table ne permet pas de compter les numéros de tirages puisqu'il n'y a qu'un enregistrement par tirage dans votre cas.

La solution conceptuelle est de dire que les tirages doivent être stockés dans la table "tirage_tbl" dont la structure est :
tirage_tbl (dtirage, num, numérocompl)
où le champ "dtirage" ne doit pas être une clé primaire puisqu'une date de tirage correspond à plusieurs numéros.
Le contenu de cette table peut être alors :
dtirage, num, numérocompl
23/2/01, 1 , 11
23/2/01, 2 , 11
23/2/01, 3 , 11
23/2/01, 12, 11
23/2/01, 14, 11
23/2/01, 10, 11
22/2/00, ...., 38
....
Ici, on voit bien que les dates se multiplient en 6 numéro de trirage, le n° complémentaire est identique pour les mêmes tirage (option simplifiable)

La requête correcte est :

Code : Tout sélectionner

SELECT dtirage, count (num) as bons_numéros FROM tirage_tbl WHERE num in (1,2,3,4,5,6) AND numérocompl = 11 GROUP BY dtirage;
La requête proposée, regroupe la table par date en comptant le nombre de n° qi répondent aux critères dans le WHERE (bons numéros)

Simplification:
Je disais que le même n° complémentaire se multiplie autant de fois comme la date de tirage. Ce qui peut être simplifié par la conception suivante :
un tirage daté a un numéro complémentaire et plusieurs numéros de tirage, on a donc une occurence de tirage qui correspond à un lot de numéros (max 6), d'où les tables suivantes :
  • 1. la table tirage : tirage_tbl (dtirage, numérocompl)
    2. et la table des numéros : numéros(dtirage, num) où les n° sont stockés par date. dtirage ici est une clé étrangère (index avec doublons)
    alors qu'elle est concidérée clé primaires dans la table tirage_tbl.
Contenu possible et requête finale:
TABLE : tirage_tbl
dtirage, numérocompl

23/2/01, 11
22/2/00, 38
....

TABLE : numéros
dtirage, num

23/2/01, 1
23/2/01, 2
23/2/01, 3
23/2/01, 12
23/2/01, 14
23/2/01, 10
22/2/00, ....
....

REQUETE : compte des bons tirages par date

Code : Tout sélectionner

SELECT tirage_tbl.dtirage , count (num) as bons_numéros FROM tirage_tbl, numéros WHERE tirage_tbl.dtirage = numéros.dtirage AND num in (1,2,3,4,5,6) AND numérocompl = 11 GROUP BY tirage_tbl.dtirage ;
L'avantage est l'économie de la taille de la base de données.

Normalement cette requête affiche, pour le jeu d'essai donné en exemple :
dtirage , bons_numéros
23/2/01, 3
...

Les dates qui n'apparaissent pas n'ont aucun bons numéro.
Si tu veux resteindre le résultat aux tirages ayant plus de 3 bons numéros, il faut écrire :

Code : Tout sélectionner

SELECT dtirage, count( num ) AS bon_numéros FROM `tirage_tbl` WHERE num IN ( 1, 2, 3, 4, 5, 6 ) AND numérocompl = 11 GROUP BY dtirage HAVING count( num ) > 3
Dans ce cas là, le même jeu d'essai de l'exemple ne retourne pas de résultat, puisqu'il n'y a que trois bons numéros pas plus.
Modifié en dernier par sadeq le 14 mars 2005, 14:09, modifié 2 fois.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 89 Messages

14 mars 2005, 14:01

Bon et bien tout d'abord un tout grand merci pour ton aide, je vais reformater le fichier en format CSV pour pouvoir mettre la DB au format que tu proposes ....

Je me rends compte qu'un cas pourrait poser problème ...
En effet, 5 bons + le complémentaire ou 6 bons n° seront-ils interprétés ?

En fait, les résultats devront se classer en:
3 bons n°;
4 bons n°;
5 bons n°;
5 bons n° + le complémentaire;
6 bons n°.

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

14 mars 2005, 14:24

Certainement, en modifiant simplement la requête en :

SELECT dtirage, count( num ) AS bons_numéros, (numérocompl LIKE 11) AS AvecComplément
FROM tirage_tbl
WHERE num
IN ( 1, 2, 3, 4, 5, 6 )
GROUP BY dtirage

Retourne por le même exemple :
dtirage, bons_numéros, AvecComplément
23/02/01, 3, 1
Modifié en dernier par sadeq le 14 mars 2005, 18:56, modifié 1 fois.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 89 Messages

14 mars 2005, 18:00

J'comprends pas ...

Le complémentaire est le 11 et je fais un select sur 1,2,3,4,5,6: le 11 n'est pas dedans. Le résultat doit être 23/02, 3.

ca devrait pas être quelque chose du style:

SELECT dtirage, count( num ) AS bon_numéros
FROM `tirage_tbl`
WHERE num
IN ( 1, 2, 3, 4, 5, 6 )
OR
num in ( 1, 2, 3, 4, 5, 6 ) AND numérocompl = 11
GROUP BY dtirage
HAVING count( num ) > 3

Désolé pour toutes ces questions ...

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

14 mars 2005, 18:54

Oui, je comprends. Tu veux dire que le complétaire ne doit pas être compris dans le compte et s'il est bon il faut le signalé par le texte "+complémentaire" ?!
Dans ce cas la requête est :

Code : Tout sélectionner

SELECT dtirage, count( num ) AS bons_numéros, IF ( numérocompl LIKE 11 , '+ complémentaire', '') AS AvecComplémentaire FROM tirage_tbl WHERE num IN ( 1, 2, 3, 4, 5, 6 ) GROUP BY dtirage HAVING count( num ) >= 3
Car le count(num) ne compte que les num's valides n°complémentaire non compris.

Maintenant l'affichage est :
dtirage, bons_numéros, AvecComplément
23/02/01, 3, + complémentaire

Puisque dans les données exemple, il y a 3 bons n° + le complémentaire ça fait 4.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 89 Messages

15 mars 2005, 10:05

J'essaye ce soir et te reviens pour te dire si c'est bon ...

Mon but, c'est d'afficher les résultats suivants:
X fois 3 bons numéros;
X fois 4 bons numéros;
X fois 5 bons numéros;
X fois 5 bons numéros + le complémentaire;
X fois 6 bons numéros.

Soit les combinaisons du lotto belge qui rapporte quelque chose ...

Donc, 3 ou 4 bons n° seulement, pas besoin de connaître si j'avais le compl ou pas ...

Je vais faire 4 requêtes différentes en modifiant chaque fois le having:
HAVING count( num ) >= 4;
HAVING count( num ) = 5;
HAVING count( num ) = 5 and numérocompl LIKE 11;
HAVING count( num ) = 6.

J'essaye et te dis quoi ....

A+,

Eléphant du PHP | 89 Messages

17 mars 2005, 10:07

Bonjour,

j'ai rempli les 2 tables avec les données réelles de l'année 1978 ... J'ai testé les requêtes, mais j'ai un souci avec celles sur les jointures ...
Dans un 1er temps, je vais laisser de côté et faire les requêtes uniquement sur les numéros hors numéros complémentaires (ne nécessite pas de jointure), comme ci-dessous:


select dtirage,count(num) AS bons_numero from tirage_tbl where num in (17,18,19,20,21,22) group by dtirage having count(num)=3;

Ca donne comme résultat:

dtirage bons-numero
1978-02-04 3
1978-04-11 3
1978-09-30 3

Comment puis-je organisser ma requête pour avoir comme résultat:

3 tirages avec 3 bons numeros.

Le but est toujours de formuler correctement la requêt SQL pour la transposer en PHP ensuite ...

Je dois quand même garder la notion de dtirage puisque je souhaite ensuite faire un lien vers une autre table se présentant comme suit:

dtirage gain 3 bons n° gain 4 bons n°
1978-02-04 5 EUR 12 EUR
1978-04-11 10 EUR 20 EUR
1978-09-30 4 EUR 30 EUR
1978-12-29 15 EUR 40 EUR

3 tirages avec 3 bons numeros vous auraient rapporté 19 EUR.

D'avance je vous remercie pour vos éclaircissements ....

A+

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

17 mars 2005, 15:34

PRIMO: Pour compter les 3 bons tirages s'ils existent, la requête est la suivante:
On compte le nombre de dates pour un même nombre de bons_numeros.

SELECT count( temp.* ) AS tirages, temp.bons_numeros
FROM (
SELECT dtirage, count( num ) AS bons_numeros
FROM tirage_tbl
WHERE num
IN ( 1, 2, 3, 4, 5, 6 )
GROUP BY dtirage
HAVING count( num ) =3
) AS temp
GROUP BY temp.bons_numeros

La requête contient une sous-requête imbriquée appellée "temp", puisque
temp doit d'abord trouver les dates des bons tirages et notre requête principale compte le nombre de dates trouvées par temp.

SECONDO: Il n'est pas logique d'intégrer le champ dtirage dans la requête principale puisque le compte concerne plusieurs dates.

Toutefois, tu peux toujours te servir de la requête "temp" séparémment pour le détail des dates.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 89 Messages

30 mars 2005, 13:25

Bonjour, je viens de tester et sql retourne une erreur de syntaxe. Par contre, la 2ème partie de la requête fonctionne:

select dtirage,count(num) AS bons_numeros from tirage_tbl where num in(17,18,19,20,21,22,23) group by dtirage having count(num)=3;

donne comme résultat:

dtirage bons_numeros
1978-02-11 2
1978-02-18 2
1978-03-11 2

Quelqu'un a-t-il une idée de l'erreur ?

Je teste la requête sur phpmyadmin 2.2.6 et la version de mysql est 3.23.49: possible que le problème vienne de là ?

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

30 mars 2005, 14:40

Le support des commandes UNION et des sous-requêtes est disponible depuis MySQL 4.0 et 4.1
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 89 Messages

30 mars 2005, 17:28

Ces sous-requêtes sont supportées par php ?

Je m'explique: si je nomme ma requête sql en $sql et que j'utilise cette variable dans mon code php, elle sera interpétée correctement ?

Si oui, je vais télécharger la dernière version de mysql ...

Crulaz
Invité n'ayant pas de compte PHPfrance

30 mars 2005, 20:32

Ces sous-requêtes sont supportées par php ?
On s'en fout de la version du php. C'est celle du mysql qui compte.

Eléphant du PHP | 89 Messages

31 mars 2005, 08:55

Ok, mais ma question était plutôt: cela vaut-il la peine de faire une requête sql avec une sous-requête sans être certain certain que celle-ci sera interprétable en php en utilisant cette requête simplement comme variable ?

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

31 mars 2005, 10:41

Dans la requête :
$sql ="
SELECT count( temp.* ) AS tirages, temp.bons_numeros
FROM (
SELECT dtirage, count( num ) AS bons_numeros
FROM tirage_tbl
WHERE num
IN ( 1, 2, 3, 4, 5, 6 )
GROUP BY dtirage
HAVING count( num ) =3
) AS temp
GROUP BY temp.bons_numeros
";

Ce qui est important pour PHP c'est les champs dans le premier SELECT.
PHP récupère normalement ces champs et les traite.
PHP ne se soucit pas du type de la requête c'est mysql qui l'exécute et renvoi le résultat à PHP.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène