Joindre 2 tables identiques

Joindre 2 tables identiques - SQL/NoSQL - Programmation

Marsh Posté le 16-03-2008 à 19:36:25    

Bonjour,
 
Je suis présentement confronté à un problème de jointure dans une requête entre 2 tables identiques (à l'exeption des données à l'intérieur).
 
Ma première table d'archive s'appel joueurs2006 et contient les statistiques de joueurs depuis la création de la ligue
Ma deuxième table s'appel joueurs et contient les statistiques de la saison en cours, donc qui n'aparraisent pas dans la première table.
 
Ce que je veux faire, c'est de joindre ces deux tables pour créer une page php CARRIÈRE.
 
voici ma requête sans jointure pour faire la somme des points des joueurs dans la table joueurs2006.
 
SELECT *, sum(pts) AS totalpts, sum(`Pro GP`) AS totalgp FROM joueurs2006 GROUP BY Name ORDER BY totalpts DESC, totalgp ASC
 
maintenant comment faire pour joindre ma table joueur sans que les colonnes ne soit ambigu et pour que le totalpts s'ajoute avec la colonne pts de la table joueurs ce qui changerait mon ORDER BY par la somme des 2 colonnes pts.

Reply

Marsh Posté le 16-03-2008 à 19:36:25   

Reply

Marsh Posté le 16-03-2008 à 22:08:33    

Pour lever l'ambiguité, il suffit de préfixer le nom des colonnes par le nom de la table et un point.
Par exemple :

...
where joueurs2006.name = joueurs.name
...
group by joueurs.name
order by joueurs.totalpts

Reply

Marsh Posté le 16-03-2008 à 23:59:06    

Oui je sais ce détail, cependant si je fais sum(joueurs.pts + joueurs2006.pts) AS totalpts ça ne me donne pas le bon nombre de pts.  Je sais que je peux faire la somme des 2 séparément, mais puis-je additionner par exemple totalpts avec un autre ALIAS d'une somme tel que sum(joueurs2006.pts) AS totalpts2,
 
 sum(totalpts + totalpts2) ne semble pas fonctionner.

Reply

Marsh Posté le 17-03-2008 à 07:43:16    

Tu as sommé comment au juste ?
Comme ça  
=>
SELECT Name, sum(j.pts) + sum(j6.pts)  
FROM joueurs2006 j6, joueurs2006 j
where j6.name = j.name  
GROUP BY Name  
ORDER BY sum(j.pts) + sum(j6.pts)   DESC


---------------
il n'y a pas que le VTT dans la vie, il y a le Snowboard aussi ...
Reply

Marsh Posté le 18-03-2008 à 03:40:32    

Non comme ça
 
$query="SELECT *, SUM(joueurs.pts + joueurs2006.pts) AS total, SUM(joueurs.`Pro GP`) as totalgp FROM joueurs, joueurs2006 GROUP BY Name ORDER BY total DESC LIMIT 0,10";
 
on dirait que pour chaque fois qu'il rencontre un joueur dans l'archive 2006 il lui additionne le total dans joueurs, ce qui donne des résultats démesurés.
 
J'ai essayé ta façon et ça ne fonctionne pas, utilisation invalide de la clause GROUP.

Reply

Marsh Posté le 18-03-2008 à 08:03:07    

* Il manque la jointure entre tes 2 tables  
et tu dois rempacer * par name car
c'est ton champ de regroupement
 
* Essaie déjà ça, l'utilisation invalide de la clause GROUP
était sans doute due au fait que je n'avais pas préfixé le champ
name  
=>  
SELECT  
joueurs.name,  
SUM(joueurs.pts + joueurs2006.pts) AS total,  
SUM(joueurs.`Pro GP`) as totalgp  
FROM joueurs, joueurs2006  
where joueurs.name = joueurs2006.name
GROUP BY joueurs.Name ;  
 
Note avec des alias ça serait  + explicite  
=>
SELECT  
j.name,  
SUM(j.pts + j6.pts) AS total,  
SUM(j.`Pro GP`) as totalgp  
FROM joueurs j, joueurs2006 j6
where j.name = j6.name
GROUP BY j.Name ;  
 
Note bien que si tu as un name apparaissant  
dans joueurs et pas dans joueurs2006
ou l'inverse => Tu n'auras aucune ligne pour ce name !
Si c'est pas ce qui te convient, il faudra utiliser
une jointure externe ...
 
 


---------------
il n'y a pas que le VTT dans la vie, il y a le Snowboard aussi ...
Reply

Marsh Posté le 19-03-2008 à 16:44:31    

Parfait ça fonctionne!!! YES!  Maintenant comme tu l'a mentionné, je veux que les joueurs se retrouvant dans joueurs2006 apparaissent même s'ils ne sont pas dans la table joueurs.
 
dois-je remplace la , de jointure par un RIGHT OUTER JOIN?

Reply

Marsh Posté le 20-03-2008 à 04:09:26    

humm.. ça fonctionne seulement pour un joueur qui apparait une seule fois dans joueurs2006... si le joueur apparait 3 fois dans joueurs 2006 il va additionner 3 fois son total dans la table joueurs à chaque fois qu'il rencontre le nom dans joueurs2006...
 
la requête doit faire la somme des pts dans joueurs 2006 et additionner une seule fois le total du joueur dans l'autre table

Reply

Marsh Posté le 20-03-2008 à 04:14:08    

OK j'ai trouvé, je devais simplement sortir l'Addition de la paranthèse...
 
SUM (j6.pts) + j.pts AS total

Reply

Marsh Posté le 31-03-2008 à 18:42:34    

$query=" SELECT  
j.Name,  
SUM(j6.pts) + j.pts AS total,  
SUM(j6.`Pro GP`) + j6.`Pro GP` as totalgp  
FROM joueurs2006 j6 RIGHT OUTER JOIN joueurs j  
ON j.Name = j6.Name  
GROUP BY j6.Name ORDER BY total DESC  
 LIMIT 0,70";
 
Il y a des joueurs dans la table joueurs2006 qui ne sont pas dans la table joueurs et je suis incapable de les faire affichier avec des OUTER JOIN, LEFT ou RIGHT.. j'ai beau changé le GROUP BY ou le j.Name par j6.Name rien ne fonctionne...  
 
comment faire?  
Merci

Reply

Marsh Posté le 31-03-2008 à 18:42:34   

Reply

Marsh Posté le 03-04-2008 à 15:32:46    

Le + simple ... et le + efficace
 
Donne quelques valeurs pour les tables  
joueurs2006 et joueurs et le résultat que tu attends
car là je vois plus trop ce que tu veux  ...


---------------
il n'y a pas que le VTT dans la vie, il y a le Snowboard aussi ...
Reply

Marsh Posté le 05-04-2008 à 23:50:20    

OK.
 
Tout dabord ma table joueurs2006 est ma table qui contient TOUTES les statistiques d'un joueur de hockey pendant les saisons précédants celle en cours.  Ma table joueurs elle contient les stats des joueurs évoluant dans ligue pendant la saison en cours.
 
Ce que je veux c'est de faire des statistiques en carrière, bref en combinant les 2.
 
Voilà le problème.
 
Mario Lemieux a joué 4 saisons dans ma ligue virtuelle (donc son nom et ses stats apparaissent 4 fois dans la table joueurs2006) et a pris sa retraite, donc ne joue pas cette saison et donc son nom n'apparait pas dans la table joueurs.
 
Lorsque je fais ma jointure entre les deux tables, je veux qu'il soit tout de même considéré même s'il n'apparait pas dans la table joueurs.  Bref, si le total de ses points le classe au 5ème rang dans l'histoire de la ligue, et bien qu'il s'affiche même si son staut n'est pas actif.
 
Présentement le code si haut me sort seulement les joueurs actifs (ceux qui apparaissent dans les deux tables en fait).
 
EXEMPLE de valeurs dans joueurs2006
joueur,gp,g,a,pts
Dany Heatley,82,50,40,90
Dany Heatley,78,44,44,88
Ilya Kovalchuk,60,32,32,64
Mario Lemieux,82,60,60,120
Mario Lemieux,77,45,45,90
 
table dans joueurs
joueurs,gp,g,a,pts
Dany Heatley,82,48,48,96
Ilya Kovalchuk,77,32,32,64
Saku Koivu,65,30,30,60
 
En principe Lemieux devrai être 2ème au total mais il n'apparaît pas étant donné qu'il n'est pas dans la table joueurs.
 
j'espère que je suis plus claire, merci.

Reply

Marsh Posté le 07-04-2008 à 16:28:08    

Ok si tu fais une jointure (INNER JOIN) : J1 entre joueurs et joueurs2006
tu auras :  
* Dany Heatley  
* Ilya Kovalchuk
 
Si tu fais une jointure externe (LEFT join) : J2 entre joueurs et joueurs2006
tu auras :
* Dany Heatley
* Ilya Kovalchuk
* Saku Koivu
 
Si tu fais une jointure externe (RIGHT join) : J3 entre joueurs et joueurs2006
tu auras :
* Dany Heatley
* Ilya Kovalchuk
* Mario Lemieux cette fois
 
Pour avoir tout le monde il faut à mon avis  
Faire un UNION entre une jointure type J2 et jointure type J3
 
Tu vois le genre ?
 
Donne voir précisement le résultat attendu
en fonction de tes 2 tables-exemple ci-dessus et  
je te donnerai la requête exacte ...  


---------------
il n'y a pas que le VTT dans la vie, il y a le Snowboard aussi ...
Reply

Marsh Posté le 07-04-2008 à 17:32:40    

Dany Heatley (274 pts)
Mario Lemieux (210 pts)
Ilya Kovalchuk (128 pts)
Saku Koivu (60 pts)  
... (jusqu'à la fin de la table, environ 800 joueurs)
 
présentement avec la requête plus haute ça me donne:
 
Dany Heatley (274 pts)
Ilya Kovalchuk (128 pts)
Saku Koivu (60 pts)  
... (jusqu'à la fin de la table, environ 800 joueurs)
 
 
merci


Message édité par larouche13 le 07-04-2008 à 17:33:41
Reply

Marsh Posté le 08-04-2008 à 16:29:01    

Essaie ceci (Sql Oracle)  
without garanty ...
=>
select j.name as MYNAME, sum(j.pts + nvl(j6.pts,0)) as MYPOINTS
From joueurs j LEFT JOIN joueurs2006 j6
ON j.Name = j6.Name  
group by j.Name
 
puis cela
=>
select j6.name, sum(j6.pts)
From joueurs j RIGHT JOIN joueurs2006 j6
ON j.Name = j6.Name  
where  j.name is null
group by j6.name
 
et pour finir la totale  
=>
select MYNAME , MYPOINTS
from  
(
select j.name as MYNAME, sum(j.pts + nvl(j6.pts,0)) as MYPOINTS
From joueurs j LEFT JOIN joueurs2006 j6
ON j.Name = j6.Name  
group by j.Name)
 
union
 
select j6.name, sum(j6.pts)
From joueurs j RIGHT JOIN joueurs2006 j6
ON j.Name = j6.Name  
where  j.name is null
group by j6.name
)
order by MYPOINTS desc
 
Note : nvl(j6.pts,0) signifie que si j6.pts est null alors  
renvoyer la valeur 0


---------------
il n'y a pas que le VTT dans la vie, il y a le Snowboard aussi ...
Reply

Marsh Posté le 08-04-2008 à 21:52:10    

$query=" SELECT  
j.name,  
SUM(j6.pts) + IFNULL(j.pts,0) AS total,  
SUM(j6.`Pro GP`) + IFNULL(j.`Pro GP`,0) as totalgp  
FROM joueurs j RIGHT OUTER JOIN joueurs2006 j6  
ON j.Name = j6.Name  
GROUP BY j.Name ORDER BY total DESC";  
 
de cette façon je réussis à faire afficher les points et le nombre de matchs joués (Pro GP) de Mario Lemieux mais son nom n'apparait pas....  peut-être moins compliqué de cette façon?

Reply

Marsh Posté le 08-04-2008 à 22:52:14    


$query=" SELECT  
j6.Name,  
SUM(j6.pts) + IFNULL(j.pts, 0) AS total,  
SUM(j6.`Pro GP`) + IFNULL(j.`Pro GP`, 0) as totalgp  
FROM joueurs2006 j6 LEFT OUTER JOIN joueurs j  
ON (j.Name = j6.Name)  
GROUP BY j6.Name ORDER BY total DESC  
 LIMIT 0,55";
 
de cette façon ça fonctionne, il s'agissait de changer la valeur de groupement j.Name par j6.Name!!
 
un gros merci,  
p.s.  la requête prend un temps énorme à s'executer!

Reply

Marsh Posté le 09-04-2008 à 08:10:14    

Bon le principal c'est que ça roule, pour le temps
voir la partie index ...
déja une jointure sur un "nom" c'est pas très orthodoxe,
ça devrait être un identifiant / clé primaire  ;-)


---------------
il n'y a pas que le VTT dans la vie, il y a le Snowboard aussi ...
Reply

Marsh Posté le 09-04-2008 à 15:30:44    

Ce qu'il y a c'est que le nom est ma seule valeur commune dans les deux tables, j'ai une valeur id mais elle est différente d'un Nom à l'autre (même chez les joueurs ayant le même nom)
 
j'ai à peine 3000 lignes dans ma jointure de table et ça me prend environ 30-35 secondes avant d'affichier un résultat

Reply

Marsh Posté le 09-04-2008 à 15:36:27    

rajoute un index sur j6.name (et eventuellement sur j.name)


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 10-04-2008 à 23:16:47    

tout à fait, ça fonctionne à merveille, merci les gars!

Reply

Marsh Posté le 11-04-2008 à 15:16:30    

Autre chose:
 
Je veux créer une page "milestone" (plateau atteint).
 
Exemple : lorsqu'un joueur atteint le plateau des 100, 200, 300, etc. points la requête l'affiche.
 
Est-ce qu'il y a un moyen d'imbriquer dans la requête une condition du genre WHERE total = multiple de 100.
 
Ou je dois me contenter d'un if ($total == 100) print blalbla; elseif ($total == 200) print blabla...
 
Merci

Reply

Marsh Posté le 11-04-2008 à 15:31:02    

C'est quoi ton Sgbd ?
 
Par exemple Sous Oracle tu peux trouver une fonction  
 
decode(mod(cpt,100) = cpt / 100, 'MULTIPLE100', cpt) as Monchamp
=>
Afficher  
MULTIPLE100  
si(decode) la division entiere(mod) de cpt par 100 <> cpt / 100
sinon afficher cpt
 
...


---------------
il n'y a pas que le VTT dans la vie, il y a le Snowboard aussi ...
Reply

Marsh Posté le 11-04-2008 à 21:45:14    

Je suis sur MYSQL.
 
L'ideal serait seulement d'ajouter la condition ou la fonction à la requête écrite plus haute.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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