Requête sur 3 tables avec une clée de liaison [Résolu]

Signaler
Messages postés
19
Date d'inscription
mercredi 20 août 2003
Statut
Membre
Dernière intervention
14 juillet 2006
-
Messages postés
268
Date d'inscription
samedi 22 février 2003
Statut
Membre
Dernière intervention
24 avril 2013
-
Bonsoir à tous,

Je rencontre en ce moment une certaine difficulté à réaliser une requête qui me permette de récupérer des informations sur 3 tables qui ont en commun une clée.
Pour mieux vous expliquer mon problème, je préfère passer par un exemple concret pour bien illustrer le résultat escompé.

je précise également que j'ai déjà posté cette question sur phpcs dans la partie Mysql mais on m'a conseigné de venir également ici...(chose que je viens de faire)

En gros, ma requête doit me renvoyer les statistiques d'un joueur qui sont contenus dans 3 tables (il est possible que ce joueur ne soit que dans une seule table, voir 2 tables, voir 3 tables ou encore aucune) mais l'exemple ci-après sera plus explicite je vous rassure...

Soit 3 tables:

1) Table_fleet qui contient les champs suivants:
player
rank
points

2)Table_points qui contient les champs suivants:
player
rank
points

3)Table_research qui contient les champs suivants:
player
rank
points

Maintenant, prenons un exemple de contenu possible (de ces 3 tables)

Contenu table_fleet:
Test----------500--------------500000
Moi-----------400--------------700000

Contenu table_points:
Test-----------200-------------136
Test2-----------1000----------80
Contenu table_research:
Test-----------300-------------1000000
Moi-------------800-------------800000

Il me faut une rêquete qui me permette de récupera les stats d'un joueur donné

Prenons par exemple pour le joueur Moi:
La requête doit me revoyer:
de la table_fleet
rank->400
points->700000

de la table_research
rank->800
points->800000

De même pour le joueur Test:
la requête doit me renvoyer:
de la table_fleet
rank->500
points->500000

de la table_points
rank->200
points->136

de la table_research
rank->300
points->1000000

Imaginons maitenant un joueur beta: la requête ne devra rien me retourner (vu que ce joueur n'est dans aucune des tables)

Actuellement je fais 3 requêtes pour arriver à ce résultat et je désire en faite, une méthode plus "propre" qui me permettrait d'avoir le même résultat mais avec une seule requête:

$sql1 = "select rank as rank_fleet,  points as points_fleet  from  table_fleet  where  player='".  $player .'"';
$sql2 = "select  rank as rank_points,  points as points_points  from  table_points  where  player='".  $player .'"';
$sql3 = "select rank as rank_research,  points as points_research  from  table_research  where  player='".  $player .'"';

Sur le forum phpcs, malalam m'a fournit une alternative qui fonctionne et me renvoie bien ce qu'il faut (voir exemple) mais le problème, c'est que celà n'est toujours pas "propre" à mon sens et j'aimerais savoir s'il n'y aurait pas une méthode plus rapide que celle qui suit:

$sql = "SELECT
  COALESCE((SELECT rank FROM ogspy_tshauniver14rank_fleet WHERE player='". $player ."'), 'n/a') AS rank_fleet,
  COALESCE((SELECT points FROM ogspy_tshauniver14rank_fleet WHERE player='". $player ."'), 'n/a') AS points_fleet,
  COALESCE((SELECT rank FROM ogspy_tshauniver14rank_points WHERE player='". $player ."'), 'n/a') AS rank_points,
  COALESCE((SELECT points FROM ogspy_tshauniver14rank_points WHERE player='". $player ."'), 'n/a') AS points_points,
  COALESCE((SELECT rank FROM ogspy_tshauniver14rank_research WHERE player='". $player ."'), 'n/a') AS rank_research,
  COALESCE((SELECT points FROM ogspy_tshauniver14rank_research WHERE player='". $player ."'), 'n/a') AS points_research";

Bon cette dernière solution me convient mais dissons que s'il y a un autre moyen, je suis preneur.

Merci d'avance pour l'attention et l'aide que vous me fournirez.

7 réponses

Messages postés
6063
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
28
Salut

Oui je pense que c'est les seules solutions
je ne vois pas ce qui te gene
pour un select aussi il te faut faire une boucle pour lire les enregistrements.

ton jeux de resultat tu le veux comment car les resultats entre le coalesce
et le union sont differents.

Tu peux le faire peut etre avec des left join

select .... from joueur j
left join flett on id_joeur = j.id
...
et les lignes ou tes joeurs nont pas de resultat seront a null

C'est a voir
Messages postés
6063
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
28
Salut

Sachant que tes tables ont la même structure

tu peux faire

select * from fleet where joueur='?'
union
select * from points where joueur='?'
union
select * from research where joueur ='?'

Je pense que c'est ce que tu recherches.

voila
Messages postés
19
Date d'inscription
mercredi 20 août 2003
Statut
Membre
Dernière intervention
14 juillet 2006

Bonsoir, le problème de cette requête, est: (avec l'exemple du joueur Moi)

 $sql = "select * from ogspy_tshauniver14rank_fleet where player='". $player ."'
union
select * from ogspy_tshauniver14rank_points where player='".$player ."'
union
select * from ogspy_tshauniver14rank_research where player ='". $player ."'";

la requête me renvoie que:

de la table_fleet
rank->400
points->700000

et ignore totalement ce qui se trouve dans la table research...

Et pour le joueur test:
de la table_fleet
rank->500
points->500000
et ignore les données dans les deux autres tables

De même si il y a aucun enregistrement dans la table_fleet, la requête me renvoie rien du tout...
Messages postés
6063
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
28
Salut

Je pense que tu dois te tromper quelque part

UNION
Renvoie
toutes les lignes qui correspond au critere

tu dois avoir un probleme de construction dans la requetes
pour que seuelement la premeiere table soit sortie et que les autre sont ignorés.

essaie de testé la requete bout part bout dans mysql

et apres avec le programme.

Si j'ai dans deux tables
table1
=
A
et table2
=
B

Alors
select * from table1 union select * from table2

-->
table3
=
A
B

je ne vois pas pas ce qui te manque

et c'est normal que pour test tu n'a rien de renvoyer
car aucune ligne ne correspond.
Messages postés
19
Date d'inscription
mercredi 20 août 2003
Statut
Membre
Dernière intervention
14 juillet 2006

Après re test, effectivement celà fonctionne, à vrai dire je ne j'avais pas que je devais utiliser une boucle pour récupérer toutes les informations...celà étant, les union sont-elles la seules solutions? avec celles de l'utisation de coalesce?

N'y a -il pas moyen de récupérer les infos désiré sans utilisation de cette boucle?

Bon voilà le bout de code:

$sql = "select * from ogspy_tshauniver14rank_fleet where player='". $player ."'
union
select * from ogspy_tshauniver14rank_points where player='".$player ."'
union
select * from ogspy_tshauniver14rank_research where player ='". $player ."'";

$query = mysql_query($sql) or die ('impossible de récupérer quelque chose: '. mysql_error() );

while($data = mysql_fetch_array($query, MYSQL_ASSOC)) {
    print_r($data);
    echo'
';
}
Messages postés
19
Date d'inscription
mercredi 20 août 2003
Statut
Membre
Dernière intervention
14 juillet 2006

Très bien, je pense que je vais opter pour la synthaxe coallesce même si j'ai autant de requête que de champ à récupérer, au moins, je ne dois pas faire de boucle pour récupérer toutes les informations et comme, c'est pour une sign dynamique, c'est pas énorme....d'autant plus que je prévois un petit système de cache pour pas consommer inutilement...

Merci à toi,...j'accepterais ta réponse en fin de semaine, si je vois qu'il y a pas autres propositions. (On ne sait jamais)
Messages postés
268
Date d'inscription
samedi 22 février 2003
Statut
Membre
Dernière intervention
24 avril 2013
3
A mon avie l;e coalesce serat moins rapide que le union je m'explique :

Dans les deux cas tu utilise les trois tables et les mêmes enregistrements de ces tables donc pas de différence sur les données utilisées mais alors que dans le cas de l'union les donnée sont simplement accumuler les une derrières les autres, le coalesce va nécéssité des test suplémentaires et en plus tu risque de devoir effectuer des jointures qui nécéssiteront encore un peu plus de calculs...