2010-05-05 8 views
1

Ma structure de table ressemble à ceci:requête SQL: Avant-dernier rang pour l'utilisateur

create table rankings (
    id IDENTITY NOT NULL, 
    user_id INT NOT NULL, 
    game_poule_id INT NOT NULL, 
    rank INT NOT NULL, 
    insertDate DATETIME NOT NULL, 
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, 
    FOREIGN KEY (game_poule_id) REFERENCES game_poules(id) ON DELETE CASCADE 
    ); 

Tous les anciens classement des utilisateurs par jeu sont enregistrés dans ce tableau. Maintenant, je veux avoir le dernier mais un rang dans le tableau pour tous les utilisateurs dans une gamepoule.

Est-ce que quelqu'un a une idée de comment réaliser cela? Merci

+0

possible (pas très agréable) S'il vous plaît poster le code que vous avez écrit jusqu'à présent. Les gens n'aiment généralement pas écrire votre code pour vous. –

+0

J'ai une clause GROUP BY maintenant SELECT user_id, rank FROM classements WHERE FK_gamePoule =? GROUP BY user_id Mais l'étape suivante est plus difficile :-) – Derk

Répondre

0

Vous devez vous joindre à la table pour obtenir les enregistrements dont vous avez besoin. Pour cette réponse, j'ai créé votre table sans les clés étrangères car elles ne sont pas nécessaires pour le faire fonctionner.

CREATE TABLE Rankings (
    id int IDENTITY NOT NULL, 
    user_id INT NOT NULL, 
    game_poule_id INT NOT NULL, 
    rank INT NOT NULL, 
    insertDate DATETIME NOT NULL 
    ); 

Insérer des données d'échantillon. Sans plus d'informations je ne peux pas simuler mieux que cela.

INSERT Rankings(user_id,game_poule_id,rank,insertDate) 
VALUES(1, 100, 3, CURRENT_TIMESTAMP-2) 
INSERT Rankings(user_id,game_poule_id,rank,insertDate) 
VALUES(1, 100, 2, CURRENT_TIMESTAMP-1) 
INSERT Rankings(user_id,game_poule_id,rank,insertDate) 
VALUES(1, 101, 6, CURRENT_TIMESTAMP) 
INSERT Rankings(user_id,game_poule_id,rank,insertDate) 
VALUES(2, 100, 5, CURRENT_TIMESTAMP-2) 
INSERT Rankings(user_id,game_poule_id,rank,insertDate) 
VALUES(2, 100, 1, CURRENT_TIMESTAMP-1) 
INSERT Rankings(user_id,game_poule_id,rank,insertDate) 
VALUES(2, 101, 2, CURRENT_TIMESTAMP) 

requête pour l'avant-dernier rang

SELECT Rankings.game_poule_id, Rankings.user_id, rank, MAX(Rankings.insertDate) 
FROM Rankings INNER JOIN 
    (SELECT game_poule_id, user_id, MAX(insertDate) max_insert_date 
     FROM rankings 
     GROUP BY game_poule_id, user_id) Max_Ranking_Date 
ON Rankings.user_id = Max_Ranking_Date.user_id 
    AND Rankings.insertDate < Max_Ranking_Date.max_insert_date 
    AND Rankings.game_poule_id = Max_Ranking_Date.game_poule_id 
GROUP BY Rankings.game_poule_id, Rankings.user_id, rank 

S'IL VOUS PLAÎT NOTE! Comme vous pouvez le voir dans les résultats, vous n'obtiendrez pas de classement pour un jeu qui n'a qu'une seule ligne par utilisateur. Mais puisque vous demandez le «dernier mais un» qui n'a de sens que pour les jeux avec plusieurs entrées.

EDIT: Je viens de réaliser que la requête que j'ai fournie ne retournera pas une ligne par utilisateur par partie. Quelqu'un veut le réparer? Je dois obtenir avec un peu de travail :)

+0

merci, j'ai aussi une autre requête SELECT * DE classement r OÙ \t FK_gamePoule = 0 ET r.insertDate = COALESCE ( (SELECT r2.insertDate DE classement OÙ r2 = r.FK_user r2.FK_user ORDER BY r2.insertDate DESC LIMIT 1 OFFSET 1), '31/12/2048 23:59:59') Mais si le vôtre c'est mieux je vais l'utiliser :-) – Derk

+0

@Derk, avez-vous réussi à faire fonctionner votre requête? Je n'ai pas eu le temps d'y regarder de plus près. – Tony

0

Une autre solution

SELECT 
    * 
FROM 
    rankings r 
WHERE 
    FK_gamePoule = 0 AND 
    r.insertDate = COALESCE(
    (SELECT 
     r2.insertDate 
    FROM 
     rankings r2 
    WHERE 
     r.FK_user = r2.FK_user ORDER BY r2.insertDate DESC 
    LIMIT 1 
    OFFSET 1), '2048-12-31 23:59:59')