tags:

views:

115

answers:

2

My table structure looks like this:

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
    );

All old rankings of users per game are saved in this table. Now I want to have the last but one rank in the table for all users in a gamepoule.

Has someone an idea how to achive this? Thanks

A: 

You need to self join the table to get the records you require. For this answer I created your table without the foreign keys as they are not required to get it to work.

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
    );

Insert some sample data. Without more information I cannot simulate any better than this.

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)

Query for the last but one rank

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 

PLEASE NOTE! As you can see from the results you will not get a ranking for a game that only has one row per user. But since you are asking for the "last but one" that only makes sense for games with multiple entries.

EDIT: I've just realised the query I have provided will not return one row per user per game. Anyone want to fix it? I have to get on with some work :)

Tony
thanks, I have also another querySELECT *FROM rankings rWHERE 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')But if yours is better I will use it :-)
Derk
@Derk, did you manage to get your query working? I haven't had time to look at in to it any further.
Tony
A: 

Another possible (not very nice) 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')
Derk