2010-10-28 2 views
0

J'ai regardé plusieurs autres questions similaires posées sur StackOverflow, mais rien ne semble correspondre à ma facture. Ma requête est légèrement plus complexe. Essentiellement, je dois trouver le rang de l'entrée.Requête SQL Server pour retourner le classement en fonction des résultats du jeu

Ma structure de table est:

TestEntry

Id, TotalTime, DateCreated 

GameResult

GameId, TestEntryId, Duration, Score 

QuestionResult

QuestionId, TestEntryId, Correct, UsersAnswer 

La requête pour calculer tous les scores se fait via les éléments suivants:

CREATE TABLE #GRS 
(
TestEntryId uniqueidentifier, 
Score int 
) 

CREATE TABLE #QRS 
(
    TestEntryId uniqueidentifier, 
    CorrectAnswers int 
) 
/* Populate temp tables with Game/Question results */ 
INSERT INTO #GRS 
SELECT 
     TestEntryId, 
     SUM(Score) AS Score 
    FROM GameResult 
    GROUP BY TestEntryId 

INSERT INTO #QRS 
SELECT 
     TestEntryId, 
     COUNT(*) CorrectAnswers 
    FROM QuestionResult 
    WHERE Correct = 1 
    GROUP BY TestEntryId 

SELECT 
     Id, ISNULL(GRS.Score,0) + (ISNULL(QRS.CorrectAnswers,0) * 25) AS Score 
    FROM TestEntry TE 
    LEFT JOIN #GRS GRS ON(GRS.TestEntryId = TE.Id) 
    LEFT JOIN #QRS QRS ON(QRS.TestEntryId = TE.Id) 
    WHERE TE.TotalTime > 0 

Basé sur une TestEntry.Id spécifique, je dois déterminer le rang de cette entrée. Proving difficile en raison de l'utilisation de tables temporaires, et le fait qu'il n'y a pas un "TotalScore" dans la table TestEntry, il est calculé dynamiquement.

+2

Quelle version de SQL Server? –

+0

Je pose la question OMG Ponies, puisqu'il y a une fonction RANK en SS08. –

+2

@Brian Driscoll: SS2005 a été le premier à supporter les fonctions analytiques - ce que je suis d'accord, c'est ce que j'utiliserais pour cela. –

Répondre

2

À moins qu'il y ait un besoin pressant de tables temporaires, videz-les et utilisez plutôt des expressions de table communes. Utilisez ensuite la fonction RANK pour obtenir un classement pour chaque identifiant.

;WITH GRS AS 
(
    SELECT 
     TestEntryId, 
     SUM(Score) AS Score 
    FROM GameResult 
    GROUP BY TestEntryId 
), 
QRS AS 
(
SELECT 
     TestEntryId, 
     COUNT(*) CorrectAnswers 
    FROM QuestionResult 
    WHERE Correct = 1 
    GROUP BY TestEntryId 
), 
Scores AS 
(
SELECT 
     Id, ISNULL(GRS.Score,0) + (ISNULL(QRS.CorrectAnswers,0) * 25) AS Score 
    FROM TestEntry TE 
    LEFT JOIN GRS ON(GRS.TestEntryId = TE.Id) 
    LEFT JOIN QRS ON(QRS.TestEntryId = TE.Id) 
    WHERE TE.TotalTime > 0 
) 
SELECT Id,Score,RANK() OVER (ORDER BY Score DESC) AS [Rank] FROM Scores 
+0

pourrait probablement être réduite à un peu moins de questions, mais je suis bien en retard pour le lit et ne peut pas être dérangé;) – spender

+0

Fonctionne un régal! Remarqué que si je filtre ensuite par un entryid, il retourne toujours un rang de 1. En mettant le dernier select dans le WITH, puis en interrogeant, c'est-à-dire SELECT Id, Score, [Rank] FROM GRR WHERE Id = ' ', que j'obtiens le bon rang pour une entrée de test individuelle. – mickyjtwin