Pour les PROS des requêtes imbriquées ? l'idée est elle faisable?

Eléphant du PHP | 58 Messages

07 oct. 2008, 23:48

J'aimerais afficher le score de certains joueurs d'une table en affichant le rang et le score par ordre décroissant de score.... je sais faire si c'est tous les joueurs que je classe mais si c'est seulement un choix de certains triés dans un premier select alors je cale....j'ai beau chercher??? :cry:

Je m'explique avec un exemple illustré :
J'ai une table LISTE AMIS

Code : Tout sélectionner

ida pseudoami pseudojoueur (ou idjoueur) 1 jean luc 2 yves marc 3 paul luc
et une table statsjoueurs

Code : Tout sélectionner

id pseudo scoremois 1 yves 3000 2 jean 6000 3 luc 1000 4 marc 7000 5 paul 2000
Pour le joueur connecté LUC, je veux afficher les scores de tous ses amis classés par meilleurs scores avec le rang devant.... si possible inclure mon pseudo dedans.....je veux donc afficher :

Code : Tout sélectionner

rang pseudo score 2 jean 6000 4 paul 2000 5 luc 1000
Quelqu'un aurait une idée de ou des requêtes à effectuer ? Merci d'avance car là je suis vraiment bloqué.
Modifié en dernier par speccy666 le 08 oct. 2008, 01:28, modifié 1 fois.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

08 oct. 2008, 00:10

eh bien, tu commences par prendre la requête qui te tries tout les joueurs, puis d'y ajouter une clause WHERE ;)

Mais donne nous la requête de base pour que nous puissions être plus précis
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Eléphant du PHP | 58 Messages

08 oct. 2008, 00:15

Tu as fait bien mieux comme réponse Zeus! dieu parmi les dieux!.... :D Bien sûr que je me doute que la réponse se situe entre la tienne et quelque chose d'un peu plus compliqué :wink:

Mais comme tu veux voir si j'ai travaillé comme un grand alors voilà le début :
$rq="select pseudoami from listeamis  WHERE pseudojoueur='$pdj'";
C'est ensuite que cela se complique et que je ne vois pas du tout... je crois qu'il faut faire une jointure sur les tables et imbriqués des SELECT dans les WHERE... :roll:

Je commence à trouver des pistes grâce à votre....heu!.....à mon opiniatreté! :wink:

Pour avoir ma liste d'amis classés par meilleurs scores je fais :
 SELECT pseudo, scoremois
FROM statsjoueurs
WHERE pseudo
IN (

SELECT pseudoami
FROM listeamis
WHERE idjoueur = '17'
)
ORDER BY scoremois DESC
LIMIT 0 , 30 
Il me reste donc à faire un COUNT(*) pour avoir le rang en passant chaque pseudo du select précédent :
SELECT COUNT(*) as rang FROM statsjoueurs  WHERE ($scoremois >= (SELECT $scoremois  FROM statsjoueurs WHERE pseudo = '$pseudo'
			ORDER BY $scoremois desc
Si vous avez mieux, je suis preneur. Merci.[/code]

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

08 oct. 2008, 03:37

Par une analyse descendante du problème on peut dire que pour avoir les scores de Luc et ses amis et leur classement général, il faut d'abord connaitre le classement général de tous les joueurs par score et connaitre les amis de Luc pour pouvoir faire une intersection.

Voici l'analyse réalisée en code SQL et testée selon le jeu d'essai que tu as donné :
# #################
# Tables de données
# #################
#
create table joueur (id int auto_increment, pseudo varchar(20), primary key(id));
replace into joueur values (1, 'jean'), (2, 'yves'), (3, 'paul'), (4, 'luc'), (5, 'marc');
#
#
create table listeamis (idjoueur int, idami int, unique(idjoueur, idami));
replace into listeamis values (4, 1), (5, 2), (4, 3);
#
#
create table statsjoueurs (annee int, mois int, idjoueur int, scoremois int, unique(annee, mois, idjoueur));
replace into statsjoueurs values (2008, 10, 2, 3000), (2008, 10, 1, 6000), 
(2008, 10, 4, 1000), (2008, 10, 5, 7000), (2008, 10, 3, 2000);
#
#
# #########
# Requête 1
# #########
# classement par score de tous les joueurs
# rang à zéro
SELECT @row :=0;
# 
SELECT @row := @row +1 AS rang, sj.idjoueur, j.pseudo, sj.scoremois
FROM statsjoueurs AS sj
JOIN joueur AS j ON sj.idjoueur = j.id
ORDER BY sj.scoremois DESC

# #########
# Requête 2
# #########
# Luc (id=4) et ses amis
SELECT DISTINCT idami AS id
FROM listeamis
WHERE idjoueur = 4
UNION SELECT 4

# ##############
# Requête finale
# ##############
# classement général de Luc et de ses amis = requête 1 jointe à la requête 2 (intersection)
# rang à zéro
SELECT @row :=0;
#
SELECT classement.rang, classement.idjoueur, classement.pseudo, classement.scoremois
FROM (
	SELECT @row := @row +1 AS rang, sj.idjoueur, j.pseudo, sj.scoremois
	FROM statsjoueurs AS sj
	JOIN joueur AS j ON sj.idjoueur = j.id
	ORDER BY sj.scoremois DESC
) AS classement
JOIN (
	SELECT DISTINCT idami AS id
	FROM listeamis
	WHERE idjoueur = 4
	UNION SELECT 4
) AS joueur_et_ses_amis 
ON joueur_et_ses_amis.id = classement.idjoueur
Comme tu vois, la difficulté résidait dans comment calculer le rang de classement, pour cela on a utilisé une variable @row qui compte les enregistrements traités par la requête.
Cette variable est globale à la requête générale, elle est initialisée au début de la transaction et incrémentée dans le SELECT.

Remarque: Dans cette analyse le problème des rangs execo (égaux) n'est pas traité.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Invité
Invité n'ayant pas de compte PHPfrance

07 nov. 2008, 01:05

Merci Sadeq! ...tes indications me sont précieuses...