2008-09-01 14 views
6

Chciałbym znaleźć różne sposoby rozwiązania mojego prawdziwego problemu: wyobraź sobie konkurs lub grę, podczas której użytkownicy zbierają zwrotnica. Musisz utworzyć zapytanie, aby wyświetlić listę użytkowników z najlepszymi wynikami "n".Zapytanie SQL o najwyższe wyniki "n" z listy

Robię przykład, aby wyjaśnić. Powiedzmy, że jest to tabela Użytkownicy, ze punkty zdobył:

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

Jeśli chcę top 3 wyniki, wynik będzie:

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

ten może być realizowany w widoku lub procedura składowana, jak chcesz. Moim docelowym parametrem db jest serwer Sql. Właściwie to rozwiązałem, ale myślę, że jest inny sposób na uzyskanie wyniku ... szybszego lub bardziej wydajnego niż mój.

Odpowiedz

9

Nietestowane, ale powinno działać:

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

@bosnic, nie sądzę, że będzie działać zgodnie z wnioskiem, że nie jestem zaznajomiony z MS SQL, ale chciałbym oczekiwać, że zwróci tylko 3 wiersze i zignoruj ​​fakt, że 3 użytkowników jest przywiązanych na 3 miejsce.

Coś jak to powinno działać:

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

@Espo dzięki za sprawdzian rzeczywistości - dodał sub-select w celu skorygowania tego.

myślę najprostszy odpowiedź jest:

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

Jeśli chcesz umieścić, że w przechowywanej proc która odbywa N jako parametr Pokochasz więc albo trzeba zrobić odczytać SQL do zmiennej następnie wykonać ją, lub rade count rzędu:

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 

lub

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 

Oba przykłady zakładają SQL Server i nie zostały przetestowane.

0

@ Rob # 37760:

select top N points from users order by points desc 

Ta kwerenda będzie wybrać tylko 3 wiersze jeśli N wynosi 3, zobacz pytanie. "Top 3" powinien zwrócić 5 wierszy.

1

Jak o:

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

Nie wiem, czy "z więzów" działa na coś innego SQL Server.

na SQL Server 2005 iw górę, można przekazać „top” numer jako parametr int:

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

Oto jeden, który działa - nie wiem, czy jest to bardziej efektywne, a to 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 

Oczywiście najpierw „z” jest stworzenie wartości, dzięki czemu można przetestować drugi z, a ostateczna Select - można zacząć w „wyniki jako ...”, jeśli były zapytanie do istniejącej tabeli.

+0

Mam podobny problem i próbowałem użyć MAX, a potem przeczytałem twoją odpowiedz i zapamiętaj DENSE_RANK. Zaoszczędziłem mnóstwo czasu. – DataGirl

0

@Matt Hamilton

Twoja odpowiedź współpracuje z powyższym przykładzie, ale nie będzie działać, jeśli zbiór danych był 100, 75, 75, 50, 50 (gdzie byłoby wrócić tylko 3 wiersze). TOP WITH TIES obejmuje tylko krawędzie ostatniego wiersza zwrócone ...

0

Crucible ma (zakładając, że SQL 2005 jest opcją).

0

Właściwie modyfikacja GDZIEGO, z wykorzystaniem DOŁĄCZENIA WEWNĘTRZNEGO, będzie znacznie szybsza.

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

Try This

select top N points from users order by points desc 
0

Hej Znalazłem wszystkie inne odpowiedzi trochę za długa i nieefektywna Moja odpowiedź byłaby:

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

to uczyni top 5 punktów