Query SQL per ottenere i migliori "n" punteggi da un elenco
-
09-06-2019 - |
Domanda
Mi piacerebbe trovare i diversi modi per risolvere un problema che ho avuto nella vita reale:immagina di organizzare un concorso, o un gioco, durante il quale gli utenti raccolgono punti.Devi creare una query per mostrare l'elenco degli utenti con i migliori punteggi "n".
Faccio un esempio per chiarire.Diciamo che questa è la tabella Utenti, con i punti guadagnati:
UserId - Points
1 - 100
2 - 75
3 - 50
4 - 50
5 - 50
6 - 25
Se voglio i primi 3 punteggi, il risultato sarà:
UserId - Points
1 - 100
2 - 75
3 - 50
4 - 50
5 - 50
Ciò può essere realizzato in una vista o in una procedura memorizzata, come desideri.Il mio db di destinazione è SQL Server.In realtà ho risolto questo, ma penso che ci siano diversi modi per ottenere il risultato...più veloce o più efficiente del mio.
Soluzione
Non testato, ma dovrebbe funzionare:
select * from users where points in
(select distinct top 3 points from users order by points desc)
Altri suggerimenti
Eccone uno che funziona: non so se sia più efficiente ed è 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
Ovviamente il primo "con" serve per impostare i valori, in modo da poter testare il secondo e selezionare il lavoro finale: potresti iniziare da "con risultati come..." se stavi eseguendo una query su una tabella esistente.
Che ne dite di:
select top 3 with ties points
from scores
order by points desc
Non sono sicuro che "con legami" funzioni su qualsiasi cosa diversa da SQL Server.
Su SQL Server 2005 e versioni successive è possibile passare il numero "top" come parametro int:
select top (@n) with ties points
from scores
order by points desc
In realtà una modifica al WHERE IN, utilizzando un INNER JOIN sarà molto più veloce.
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
@bosnic, non penso che funzionerà come richiesto, non ho molta familiarità con MS SQL ma mi aspetterei che restituisca solo 3 righe e ignori il fatto che 3 utenti sono a pari merito per il 3 ° posto.
Qualcosa del genere dovrebbe funzionare:
select userid, points
from scores
where points in (select top 3 points
from scores
order by points desc)
order by points desc
@Rob#37760:
select top N points from users order by points desc
Questa query selezionerà solo 3 righe se N è 3, vedere la domanda."Primi 3" dovrebbe restituire 5 righe.
@Espo grazie per il controllo della realtà: ho aggiunto la selezione secondaria per correggerlo.
Penso che la risposta più semplice sia:
select userid, points from users
where points in (select distinct top N points from users order by points desc)
Se vuoi inserirlo in un proc memorizzato che accetta N come parametro, dovrai leggere l'SQL in una variabile e quindi eseguirlo, oppure eseguire il trucco del conteggio delle righe:
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
O
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
Entrambi gli esempi presuppongono SQL Server e non sono stati testati.
@Matt Hamilton
La tua risposta funziona con l'esempio sopra ma non funzionerebbe se il set di dati fosse 100, 75, 75, 50, 50 (dove restituirebbe solo 3 righe).TOP CON LEGAMI include solo le legature di valore dell'ultima riga restituita...
Crucible l'ha capito (supponendo che SQL 2005 sia un'opzione).
Hey ho trovato tutte le altre risposte un po 'lunghe e inefficienti la mia risposta sarebbe:
select * from users order by points desc limit 0,5
questo renderà i primi 5 punti
Prova questo
select top N points from users order by points desc