2009-07-16 10 views
21

Ich habe eine Tabelle, die einige Spalten: Benutzer, Kategorie, WertSQL Server Query für Rank (RowNumber) und Groupings

Und ich möchte eine Abfrage machen, die mir ein Ranking geben, der alle Nutzer von der Wert, aber für die Kategorie zurückgesetzt.

Beispiel:

user1 CategoryA 10 
user2 CategoryA 11 
user3 CategoryA 9 
user4 CategoryB 3 
user1 CategoryB 11 

die Abfrage zurückkehren würde:

Rank User Category 
1  user2 CategoryA 
2  user1 CategoryA 
3  user3 CategoryA 
1  user1 CategoryB 
2  user4 CategoryB 

Irgendwelche Ideen?

Ich schreibe die Abfrage und geben Sie die Kategorie, es funktioniert, aber ich muss Schleifen schreiben und es ist sehr langsam.

+0

Meine aktuelle Abfrage: SELECT Rang() über (Sortieren nach Wert, Benutzer, Kategorie) als Reihen, Kategorie, Benutzer aus Tabelle 1 Gruppe nach Benutzern, Kategorie, Preis Sortieren nach Rängen asc – bladefist

Antwort

43

Use "Partition durch" in der Rangliste Funktion OVER clause

SELECT 
    Rank() over (Partition by Category Order by Value, User, Category) as ranks, 
    Category, User 
FROM 
    Table1 
Group By 
    User, Category, Value 
Order by 
    ranks asc 
+0

1.261.473 Datensätze in 33 Sekunden (mit einer Tabelle beitreten, fügte ich hinzu, dass nicht in der Frage enthalten war). Dank – bladefist

+0

Um die gleiche Ausgangsreihenfolge zu erhalten, wie die Frage Ausgabe zeigt, Reihenfolge nach Kategorie, Ränge. Außerdem gibt der Benutzer den DB-Benutzer (d. H. Dbo) zurück und muss zitiert werden, um zu der Spalte mit dem Namen Benutzer zu gelangen. (Zitiert entweder [Benutzer] oder mit quoted Identifier auf "Benutzer".) –

+0

@Shannon: Ich begann mit der Abfrage, die OP in einem Kommentar hinzugefügt. Ich wollte nur die Partition von – gbn

3
Select User, Category, 
    (Select Count(*) From Table 
     Where Category = A.Category 
     And Value <= A.Value) Rank 
From Table A 
Order By Category, Value 

Wenn Value Duplikate haben können, müssen Sie dann entscheiden, ob Sie die Betrogenen (equivilent zu RANK) oder nicht (equivilent zu DENSE_RANK, thanx @shannon)

Ordinary Rank 'count' wollen:

Select User, Category, 
    (Select 1 + Count(*) From Table -- "1 +" gives 1-based rank, 
     Where Category = A.Category -- take it out to get 0-based rank 
     And Value < A.Value) Rank 
From Table A 
Order By Category, Value 

"Dense" Rang:

Select User, Category, 
    (Select 1 + Count(Distinct Value) -- "1 +" gives 1-based rank, 
     From Table      -- take it out to get 0-based rank 
     Where Category = A.Category  
     And Value < A.Value) Rank 
From Table A 
Order By Category, Value 
+0

sehr ineffizient. Die Tatsache, dass er RANK verwendet, bedeutet zumindest SQL 2005. – gbn

+0

Wahr. SQL 2008. Ich werde alle Antworten versuchen – bladefist

+0

Aber a) Klarheit kommt zuerst, dann Effizienz ... und b) Problem ist über die Benutzer, so dass wir nicht Milliarden von Aufzeichnungen sprechen ... –