2010-01-19 5 views
6

Ich fand eine Frage, die dieser sehr ähnlich war, aber mit Funktionen, die nur für Oracle scheinen. Ich möchte dies in SQL Server tun.Holen Sie die Zeile mit dem Max-Wert für eine Spalte in SQL Server

Ich habe eine Tabelle wie folgt aus:

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

Jeder Benutzer mehrere Zeilen haben kann, mit unterschiedlichen Werten für Counter in jeder Reihe. Ich muss die Zeilen mit dem höchsten Counter Wert für jeden Benutzer finden.

Wie kann ich dies in SQL Server 2005 tun?

Das beste, was ich kann, ist eine Abfrage gibt die MAX(Counter) für jede UserID, aber ich brauche die gesamte Zeile wegen der anderen Daten in dieser Tabelle nicht in meiner Tabelle Definition der Einfachheit halber gezeigt.

EDIT: Es ist mir durch einige der Antworten in diesem Beitrag, dass ich ein wichtiges Detail vergessen habe, auf mich aufmerksam geworden. Es ist möglich, 2 + Zeilen zu haben, in denen eine Benutzer-ID denselben MAX-Zählerwert haben kann. Beispiel unten aktualisiert für was die erwarteten Daten/Ausgaben sein sollten.

Mit diesen Daten:

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

Ich mag diese Ergebnisse für den doppelten MAX-Wert, in das erste Auftreten wählen, was auch immer, um SQL Server sie auswählt. Welche Zeilen zurückgegeben werden, ist nicht wichtig, in diesem Fall, solange der Benutzer-ID/Zähler-Paare sind verschieden:

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

Antwort

9

ich mag für diesen Fall einen allgemeinen Tabellenausdruck verwenden, mit einem geeigneten ROW_NUMBER() Funktion in i 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 

, dass die Daten über die Benutzer-ID partitioniert, Aufträge durch Zähler (absteigend) für jeden Benutzer, und dann Etiketten jeder der Reihen mit 1 für jeden Benutzer zu starten. Wählen Sie nur die Zeilen mit einer 1 für die Hausnummer und Sie haben Ihre max. Werte pro Benutzer.

Es ist so einfach :-) Und ich bekomme Ergebnisse etwas wie folgt aus:

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

nur ein Eintrag pro Benutzer, unabhängig davon, wie viele Zeilen pro Benutzer zufällig den gleichen Maximalwert haben.

+3

@marc_s: Serien-Downvoter - du bist der Dritte, den ich gesehen habe, einschließlich mir. –

+0

@OMGPonies: yeah, ich denke ... Ich verstehe es auf einem eigensinnigen Stück, oder wenn Sie einen eklatanten Fehler in Ihrem Beitrag haben ...... Anyhoo ..... –

+1

@marc_s: +1: Every jetzt & dann passiert es in SQL-Fragen. –

0

Es gibt mehrere Möglichkeiten, dies zu tun, werfen Sie einen Blick auf diese Including an Aggregated Column's Related Values sind mehrere Verfahren einschließlich der Leistung gezeigt Unterschiede

Hier ist ein Beispiel

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

Was passiert in dem Fall, wenn Sie den gleichen Benutzer mit 2 Zählungen das gleiche haben? –

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

Was passiert in dem Fall, wenn Sie den gleichen Benutzer mit 2 Zählungen das gleiche haben? –

+0

Das muss "und m.Counter == mm.MaxCounter" sein, sonst erhalten Sie einen Fehler –

+0

Ja, Tippfehler, behoben. – RedFilter

0

Versuchen Sie dies ... Ich bin mir ziemlich sicher, dass dies der einzige Weg ist, um wirklich sicherzustellen, dass Sie eine Zeile pro Benutzer bekommen.

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

Sie haben ziemlich viele Probleme in dieser Abfrage mit mehrdeutigen Spaltennamen und anderen Dingen .... –

+0

ya ich schrieb es schnell ... aber die Idee funktioniert. Ich werde es reparieren. – anthonyv

2

Ich denke, das wird Ihnen helfen.

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

Das 'distinct' ist nicht notwendig. Eine 'Gruppe von' wird das automatisch tun. – Ben

+0

Das hat mir geholfen, aber wie funktioniert das? – zzapper

Verwandte Themen