2008-09-01 5 views
6

Ich würde gerne die verschiedenen Möglichkeiten finden, ein echtes Leben Problem zu lösen Ich hatte: Stellen Sie sich einen Wettbewerb, oder ein Spiel, während der die Benutzer sammeln Punkte. Sie müssen eine Abfrage erstellen, um die Liste der Benutzer mit den besten "n" Werten anzuzeigen.SQL-Abfrage, um die besten "n" Punkte aus einer Liste zu bekommen

Ich mache ein Beispiel zur Klärung. Lassen Sie uns sagen, dass dies die Tabelle Benutzer ist, wobei die Punkte verdient:

UserId - Points 
1  - 100 
2  - 75 
3  - 50 
4  - 50 
5  - 50 
6  - 25 

Wenn ich die Top-3-Scores wollen, wird das Ergebnis sein: kann

UserId - Points 
1  - 100 
2  - 75 
3  - 50 
4  - 50 
5  - 50 

Dies in einer Ansicht oder ein realisiert werden gespeicherte Prozedur, wie Sie möchten. Meine Zieldatenbank ist Sql Server. Eigentlich habe ich das gelöst, aber ich denke, es gibt andere Wege, das Ergebnis zu erreichen ... schneller oder effizienter als meins.

Antwort

9

Ungeprüfte, aber sollte funktionieren:

select * from users where points in 
(select distinct top 3 points from users order by points desc) 
1

@bosnic, ich glaube nicht, dass funktioniert wie gewünscht, ich bin nicht so vertraut mit MS SQL, aber ich würde erwarten, dass es nur drei Zeilen zurückgeben und ignoriere die Tatsache, dass 3 Benutzer für den 3. Platz gebunden sind.

So etwas sollte funktionieren:

select userid, points 
    from scores 
    where points in (select top 3 points 
         from scores 
         order by points desc) 
    order by points desc 
0

@Espo Dank für die Reality-Check - hat die Unterauswahl für das korrigieren.

Ich denke, die einfachste Antwort ist:

select userid, points from users 
where points in (select distinct top N points from users order by points desc) 

Wenn Sie, dass in einem gespeicherten proc setzen wollen, die N als Parameter annimmt, dann werden Sie entweder die SQL in eine Variable tun lesen führen sie es dann, oder tun, um die Zeilenanzahl Trick:

declare @SQL nvarchar(2000) 
set @SQL = "select userID, points from users " 
set @SQL = @SQL + " where points in (select distinct top " + @N 
set @SQL = @SQL + " points from users order by points desc)" 

execute @SQL 

oder

SELECT UserID, Points 
FROM  (SELECT ROW_NUMBER() OVER (ORDER BY points DESC) 
     AS Row, UserID, Points FROM Users) 
     AS usersWithPoints 
WHERE Row between 0 and @N 

Beide Beispiele gehen von SQL Server aus und wurden nicht getestet.

0

@ Rob # 37760:

select top N points from users order by points desc 

Diese Abfrage nur drei Zeilen auswählen, wenn N 3 ist, die Frage sehen. "Top 3" sollte 5 Zeilen zurückgeben.

1

Wie wäre:

select top 3 with ties points 
from scores 
order by points desc 

Nicht sicher, ob "mit Verbindungen" auf etwas anderes die SQL Server funktioniert.

auf SQL Server 2005 und höher, können Sie die „top“ Nummer als int-Parameter übergeben:

select top (@n) with ties points 
from scores 
order by points desc 
4

ein Hier, das funktioniert - ich weiß nicht, ob es effizienter ist, und es ist SQL Server 2005+

with scores as (
    select 1 userid, 100 points 
    union select 2, 75 
    union select 3, 50 
    union select 4, 50 
    union select 5, 50 
    union select 6, 25 
), 
results as (
    select userid, points, RANK() over (order by points desc) as ranking 
    from scores 
) 
select userid, points, ranking 
from results 
where ranking <= 3 

Offensichtlich ist die erste „durch“ ist, um die Werte zu setzen, so dass Sie die zweite mit testen können, und letzte Auswahl Arbeit - man könnte „wie er mit den Ergebnissen ...“ beginnen, wenn Sie waren Abfrage einer vorhandenen Tabelle.

+0

Ich habe ein ähnliches Problem und versuchte MAX zu verwenden und dann las ich dein antworte und erinnerst dich an DENSE_RANK. Sparte mir viel Zeit. – DataGirl

0

@ Matt Hamilton

Ihre Antwort arbeitet mit dem obigen Beispiel würde aber nicht funktionieren, wenn der Datensatz 100 war, 75, 75, 50, 50 (wo es nur drei Zeilen zurückgeben würde). TOP WITH TIES enthält nur die Bindungen der letzten zurückgegebenen Zeile ...

0

Crucible bekam es (vorausgesetzt, SQL 2005 ist eine Option).

0

Eigentlich eine Modifikation der WHERE IN, mit einem INNER JOIN wird viel schneller sein.

SELECT 
    userid, points 
FROM users u 
INNER JOIN 
(
    SELECT DISTINCT TOP N 
     points 
    FROM users 
    ORDER BY points DESC 
) AS p ON p.points = u.points 
0

Versuchen Sie, diese

select top N points from users order by points desc 
0

Hey ich alle anderen Antworten gefunden Bit lang und ineffizient Meine Antwort wäre:

select * from users order by points desc limit 0,5

dies machen Top-5-Punkte

Verwandte Themen