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.

È stato utile?

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top