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é.