8795 sujets

Développement web côté serveur, CMS

Bonjour.

Une chose qui me semblait facile à réaliser me donne beaucoup plus de files à retordre que prévu. J'ai trouvé des pistes sur Internet, mais il me manque un dernier coup de main, pour comprendre.

Explication :

Je veux simplement obtenir un classement en fonction du score de mes joueurs. Je veux interroger la BDD et lui demander "calcule moi la position du joueur X par mis tous les autres". Ex : TOTO est 487e...

Actuellement voilà mon code qui me convient parfaitement, seul le Classement manque.

$sql = "SELECT * FROM scores,users WHERE scores.id_user = users.id AND level_name='$global_level_name' ORDER BY score DESC LIMIT 5"


PS : Je fais une jointure entre les deux tables pour avoir l'ensemble des infos.

PS 2 : J'ai trouvé ce code qui pourrait m'aider je pense, mais je n'arrive pas à le transposer à mon cas.

Merci du coup de main.

mysql> SELECT a.name, -> (SELECT COUNT(DISTINCT b.score) FROM scores AS b WHERE b.score >= a.score) AS 'position' -> FROM scores AS a WHERE a.name = 'pouet' ORDER BY position ASC;


mysql> SELECT a.name,-> (SELECT COUNT(DISTINCT b.score) FROM scores AS b WHERE b.score >= a.score) AS 'position'-> FROM scores AS a WHERE a.score < 200 ORDER BY position ASC;

Modifié par Pattaya (06 Nov 2009 - 21:37)
Pour trouver le classement d'un joueur donné, c'est en général une requête du genre :
select count(*) from joueurs where score > (select score from joueurs where nom = 'pouet pouet');

Bon là c'est un cas simple, ça prend pas en compte les ex-aoequo... et puis il n'y a pas besoin de la sous-requête si tu as déjà récupérer le score du joueur.
Arf, navré QuentinC mais je n'arrive toujours pas à voir la solution dans ta réponse. J'ai visiblement encore des difficultés avec SQL. Ta requête serait en addition « à la suite de la mienne » ?

$sql = "SELECT * FROM scores,users WHERE scores.id_user = users.id AND level_name='$global_level_name' ORDER BY score DESC LIMIT 5"


Tu ne fais pas de jointure entre mes deux tables « Users et Scores, scores.id_user = users.id.

Comment ton FROM joueurs WHERE score peut fonctionner ?
Modifié par Pattaya (05 Nov 2009 - 23:55)
JE n'ai pas du tout tenu compte de tes exemples à toi. C'était juste un exemple rapide.
Par contre pour joindre les deux requêtes en une seule, ça me paraît chaud, même avec un group by.

EDIT : Au fait, tu fais déjà une sorte de classement, puisque tu récupères déjà les joueurs par score décroissant. IL ne te suffirait pas de rajouter la position en php ?
Modifié par QuentinC (06 Nov 2009 - 06:34)
Je viens de rajouter la position en PHP pour une partie de ma page scores, cependant il me faut impérativement pouvoir calculer le Rank pour l'autre partie de la page. Notamment pour la recherche d'un joueur. L'utilisateur tape un nom de joueur, la BDD cherche le joueur et affiche son classement.

Actuellement j'ai ce code-là, mais toujours pas de classement

"SELECT * FROM scores,users WHERE scores.id_user = users.id AND name='$find_player' ORDER BY score"

Modifié par Pattaya (06 Nov 2009 - 17:30)
Peux-tu poster un extrait de la structure de tes tables user et score ? juste les éléments significatifs, parce que certaines choses ne me paraissent pas tout à fait claires.
Voilà la structure de ma BDD, trois tables.

Table users
id
password
mail
name
location

Table scores
id
level_name
id_user
score
date

Table friends
id
id_user
id_friend

Jointure possible
scores.id_user = users.id
friends.id_user = users.id

La table friends « le PlayerA peut ajouter des joueurs dans sa liste d'ami. Quand une des personnes de cette liste bat le score du PlayerA, un mail est envoyé au PlayerA pour lui donné l'info » une sorte de Follower.
Essaie ça, sans garantie :

select u.*, s.*,
(select count(*) from scores t where t.level_name = s.level_name and t.score > s.score) as classement
from users u
left join scores s on u.id = s.user_id
where u.name = 'toto'
oreder by s.score desc

Ca devrait te renvoyer le palmarès du joueur toto, avec son score et son classement pour chaque niveau.
Je ne suis pas certain sur deux points : j'ai un doute sur la possibilité de pouvoir faire référence à la super-requête depuis la sous-requête d'une part et puis je ne suis pas sûr non plus qu'on puisse ajouter une colonne de cette façon dans la super-requête. A tester. Problème, ça risque d'être une requête assez consommatrice en ressources. IL doit y avoir un moyen de remplacer la sous-requête par un group by.
Modifié par QuentinC (06 Nov 2009 - 21:10)
Il y avait une petite faute de frape sur le ORDER, voilà le code réécrit.


$query = ("SELECT u.*, s.*,(SELECT COUNT(*) FROM scores t WHERE t.level_name = s.level_name AND t.score > s.score) as classement FROM users u left join scores s on u.id = s.user_id WHERE u.name = 'Toto' ORDER BY s.score desc")or die(mysql_error());


Réponse du serveur : Unknown column 's.user_id' in 'on clause'
Salut,

je ne vois pas bien l'intérêt de tout faire en une seule requête d'autant plus qu'à chaque fois il s'agit de refaire un count(*) dans la table score.

Ce serait bien plus simple de ne faire cette requête qu'une seule fois puis de lancer celle qui te donne le classement par score...

Ce qui donne en fonction de ton point d'entrée :
 SELECT count(*) as nb_users FROM scores WHERE level_name = '$global_level_name'

...

SELECT u.id, u.name, s.score FROM scores s JOIN users u ON s.id_user = u.id
WHERE level_name = '$global_level_name' ORDER BY score DESC LIMIT 5  

ou
SELECT count(*) as nb_users from scores where level_name = (
SELECT level_name from scores s join users u on s.id_user = u.id where u.name = '$name')

...

SELECT u.id, u.name, s.score FROM scores s JOIN users u ON s.id_user = u.id WHERE level_name = (
SELECT level_name from scores s join users u on s.id_user = u.id where u.name = '$name')
ORDER BY score DESC LIMIT 5

Modifié par Heyoan (07 Nov 2009 - 09:44)