2010-01-19 9 views
6

Ho trovato una domanda molto simile a questa, ma che utilizza funzionalità che sembrano esclusive di Oracle. Sto cercando di farlo in SQL Server.Recupera la riga con il valore Max per una colonna in SQL Server

Ho una tabella come questa:

MyTable 
-------------------- 
MyTableID INT PK 
UserID  INT 
Counter INT 

Ogni utente può avere più righe, con diversi valori di Counter in ogni fila. Devo trovare le righe con il valore più alto di Counter per ciascun utente.

Come posso farlo in SQL Server 2005?

Il meglio che riesco a trovare è una query restituisce il MAX(Counter) per ogni UserID, ma ho bisogno dell'intera riga a causa di altri dati in questa tabella non mostrati nella mia definizione di tabella per semplicità.

EDIT: È giunto alla mia attenzione da alcune delle risposte in questo post, che ho dimenticato un dettaglio importante. È possibile avere più di 2 righe in cui un ID utente può avere lo stesso valore di contatore MAX. Esempio sotto aggiornato per quale dovrebbe essere il dato/output atteso.

Con questi dati:

MyTableID UserID Counter 
--------- ------- -------- 
1   1   4 
2   1   7 
3   4   3 
4   11  9 
5   11  3 
6   4   6 
... 
9   11  9 

Voglio che questi risultati per i valori MAX duplicati, selezionare la prima occorrenza in qualsiasi ordine di SQL Server li seleziona. Quali righe vengono restituite non è importante in questo caso fino a quando l'UserID/coppie di contatore sono distinti:

MyTableID UserID Counter 
--------- ------- -------- 
2   1   7 
4   11  9 
6   4   6 

risposta

9

mi piace usare un'espressione di tabella comune per tale caso, con un adeguato ROW_NUMBER() nei t:

WITH MaxPerUser AS 
(
    SELECT 
    MyTableID, UserID, Counter, 
    ROW_NUMBER() OVER(PARTITION BY userid ORDER BY Counter DESC) AS 'RowNumber' 
    FROM dbo.MyTable 
) 
SELECT MyTableID, UserID, Counter 
FROM MaxPerUser 
WHERE RowNumber = 1 

che suddivide i dati sul UserID, ordini esso dal contatore (discendente) per ciascun utente, e quindi etichette ciascuna delle righe che iniziano con 1 per ogni utente. Seleziona solo quelle righe con 1 come numero di riferimento e hai il massimo. valori per utente.

È così facile :-) e ottengo risultati qualcosa di simile:

MyTableID UserID Counter 
    2   1  7 
    6   4  6 
    4   11  9 

una sola partecipazione per utente, indipendentemente dal numero di righe per utente capita di avere lo stesso valore max.

+3

@marc_s: downsoter seriale: sei il terzo che ho visto, incluso me stesso. –

+0

@OMGPonies: sì, immagino .... lo capisco su un pezzo supponente, o quando hai un errore evidente nel tuo post ...... anyhoo ..... –

+1

@marc_s: +1: Ogni ora e poi succede nelle domande SQL. –

0

Ci sono diversi modi per fare questo, dare un'occhiata a questo Including an Aggregated Column's Related Values diversi metodi sono mostrati tra cui le prestazioni differenze

Ecco un esempio

select t1.* 
from(
select UserID, max(counter) as MaxCount 
from MyTable 
group by UserID) t2 
join MyTable t1 on t2.UserID =t1.UserID 
and t1.counter = t2.counter 
+0

Cosa succede nel caso in cui lo stesso utente abbia 2 conteggi uguali? –

0
select m.* 
from MyTable m 
inner join (
    select UserID, max(Counter) as MaxCounter 
    from MyTable 
    group by UserID 
) mm on m.UserID = mm.UserID and m.Counter = mm.MaxCounter 
+0

Cosa succede nel caso in cui lo stesso utente abbia 2 conteggi uguali? –

+0

Deve essere 'and m.Counter == mm.MaxCounter' altrimenti viene visualizzato un errore –

+0

Sì, errore di battitura, risolto. – RedFilter

0

Prova questo ... Sono sicuro che questo è l'unico modo per assicurarti veramente di ottenere una riga per utente.

SELECT MT.* 
FROM MyTable MT 
    INNER JOIN (
     SELECT MAX(MID.MyTableId) AS MaxMyTableId, 
      MID.UserId 
     FROM MyTable MID 
      INNER JOIN (
       SELECT MAX(Counter) AS MaxCounter, UserId 
       FROM MyTable 
       GROUP BY UserId 
      ) AS MC 
       ON (MID.UserId = MC.UserId 
        AND MID.Counter = MC.MaxCounter) 
     GROUP BY MID.UserId 
    ) AS MID 
     ON (MID.UserId = MC.UserId 
      AND MID.MyTableId = MC.MaxMyTableId) 
+0

Hai qualche problema in questa query con nomi di colonne ambigue e altre cose .... –

+0

ya l'ho scritto velocemente ... ma l'idea funziona. Lo aggiusterò. – anthonyv

2

Penso che questo ti aiuterà.

SELECT distinct(a.userid), MAX(a.counterid) as counterid 
FROM mytable a INNER JOIN mytable b ON a.mytableid = b.mytableid 
GROUP BY a.userid 
+3

Non è necessario il 'distinto'. Un 'group by' lo farà automaticamente. – Ben

+0

Questo ha fatto il trucco per me, ma come funziona? – zzapper

Problemi correlati