Wie verwende ich ROW_NUMBER ()?


175

Ich möchte das nutzen ROW_NUMBER(), um ...

  1. Um das max(ROW_NUMBER())-> Oder ich denke, dies wäre auch die Anzahl aller Zeilen

Ich habe versucht:

SELECT max(ROW_NUMBER() OVER(ORDER BY UserId)) FROM Users

aber es schien nicht zu funktionieren ...

  1. Um ROW_NUMBER()eine bestimmte Information zu verwenden, dh. Wenn ich einen Namen habe und wissen möchte, aus welcher Zeile der Name stammt.

Ich nehme an, es wäre etwas Ähnliches wie das, was ich für # 1 versucht habe

SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'

aber das hat auch nicht funktioniert ...

Irgendwelche Ideen?

Antworten:


150

Für die erste Frage, warum nicht einfach verwenden?

SELECT COUNT(*) FROM myTable 

um die Zählung zu bekommen.

Und für die zweite Frage ist der Primärschlüssel der Zeile, was zur Identifizierung einer bestimmten Zeile verwendet werden soll. Versuchen Sie nicht, die Zeilennummer dafür zu verwenden.


Wenn Sie Row_Number () in Ihrer Hauptabfrage zurückgegeben haben,

SELECT ROW_NUMBER() OVER (Order by Id) AS RowNumber, Field1, Field2, Field3
FROM User

Wenn Sie dann 5 Zeilen zurückgehen möchten, können Sie die aktuelle Zeilennummer verwenden und die folgende Abfrage verwenden, um die Zeile mit currentrow -5 zu bestimmen

SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
     FROM User ) us 
WHERE Row = CurrentRow - 5   

In meiner Situation erhalte ich eine Benutzer-ID und möchte die Benutzer-ID erhalten, die eine bestimmte Anzahl von Zeilen zurückgibt. Was ist, wenn eine Zeile gelöscht wird? In diesem Fall kann ich nicht einfach UserId - Offset verwenden, da ich dann nicht den richtigen Datensatz erhalten würde.

Es ist besser, select count (1) aus mytable zu verwenden, um die Anzahl der Datensätze auszuwählen. Dies ist so schnell und effizient
Sivajith

46

Obwohl ich anderen zustimme, dass Sie count()die Gesamtzahl der Zeilen ermitteln können, können Sie Folgendes verwenden row_count():

  1. So erhalten Sie die Gesamtzahl der Zeilen:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp
  2. So erhalten Sie die Zeilennummern mit dem Namen Matt:

    with temp as (
        select name, row_number() over (order by id) as rownum
        from table_name
    )
    select rownum from temp where name like 'Matt'

Sie können die erste oder letzte Zeile für Matt weiter verwenden min(rownum)oder max(rownum)abrufen.

Dies waren sehr einfache Implementierungen von row_number(). Sie können es für komplexere Gruppierungen verwenden. Überprüfen Sie meine Antwort zur erweiterten Gruppierung, ohne eine Unterabfrage zu verwenden


Könnten Sie bitte erklären, wie Sie die Spalte auswählen, in der verwendet wird order by X? Mit anderen Worten, wie sollte Xbestimmt werden? Vielen Dank!
Kevin Meredith

@ KevinMeredith: Dies order by Xist die Reihenfolge, in der Sie die Reihenfolge bestimmen, in der die Zeilen zugewiesen werden ROW_NUMBERS(). Denken Sie daran, dass Tabellen in relationalen Datenbanken trotz ihres Namens keine formale Reihenfolge haben. Wenn Sie also eine Zeile "1" oder "10" oder "1337" aufrufen möchten, müssen Sie sie zuerst mit einer ORDER BYKlausel sortieren ist derjenige, der in die OVER (ORDER BY X)Klausel geht.
Wtrmute

25

Wenn Sie die Gesamtzahl der Zeilen der Tabelle zurückgeben müssen, können Sie eine alternative Methode zur SELECT COUNT(*)Anweisung verwenden.

Da SELECT COUNT(*)ein vollständiger Tabellenscan durchgeführt wird, um die Zeilenanzahl zurückzugeben, kann eine große Tabelle sehr lange dauern. sysindexesIn diesem Fall können Sie stattdessen die Systemtabelle verwenden. Es gibt eine ROWSSpalte, die die Gesamtzahl der Zeilen für jede Tabelle in Ihrer Datenbank enthält. Sie können die folgende select-Anweisung verwenden:

SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2

Dadurch wird die Zeit, die Ihre Abfrage benötigt, drastisch reduziert.


Sie haben Recht mit dem vollständigen Tabellenscan, aber beachten Sie, dass es sich nicht unbedingt um einen Clustered-Index-Scan handelt, da hierfür möglicherweise ein Nicht-Clustered-Index verwendet wird
yoel halb

2
Dies gilt auch nur für SQL-Server, da andere RDMBS die Auswahlanzahl optimiert haben
yoel halb

7

ROW_NUMBER() Gibt eine eindeutige Nummer für jede Zeile zurück, die mit 1 beginnt. Sie können diese einfach verwenden, indem Sie einfach schreiben:

ROW_NUMBER() OVER (ORDER BY 'Column_Name' DESC) as ROW_NUMBER

Sie können den Unterschied zwischen finden Row_number(), Rank()und Dense_Rank() hier .


7

Sie können dies verwenden, um den ersten Datensatz abzurufen, in dem die Klausel enthalten ist

SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum 
FROM     Users 
WHERE    UserName = 'Joe'
ORDER BY rownum ASC

4
SELECT num, UserName FROM 
 (SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
  From Users) AS numbered
WHERE UserName='Joe'

Um alle Zeilen aufzulisten - ansonsten zählst du nur die Zeilen auf, in denen der Benutzername Joe ist, was nicht das Ziel ist ;-).
Alex Martelli

1
@ Matt: Nenn mich einen Pedanten; Ich bevorzuge entweder "abgeleitete Tabelle" oder "anonyme Ansicht" gegenüber dem Begriff "Unterauswahl".
mechanisches

1
@adam, da ich auch ein Pedant bin - würde "verschachtelte Auswahl" dich glücklicher machen? Ich mag es nicht, Begriffe wie Tabelle oder Ansicht zu verwenden, wenn kein TABLEoder VIEWSchlüsselwort vorhanden ist ... aber SELECTsicher! -)
Alex Martelli

@Alex: Sie präsentieren einen gültigen Punkt. "Nested Select" funktioniert hervorragend für mich :) Übrigens, ich lese sehr gerne die Anekdoten, die Sie Ihren Kommentaren und Antworten hinzufügen.
mechanisches

@Adam, danke! Manchmal sind meine Antworten wie hier sehr nackter Code, aber ich liebe es, sie zu konkretisieren, wenn ich eine freie Minute habe ;-).
Alex Martelli

4

Kann hier nicht mit der Frage zusammenhängen. Aber ich fand, dass es nützlich sein könnte, wenn man ROW_NUMBER-

SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID 
FROM #Any_Table

3
select 
  Ml.Hid,
  ml.blockid,
  row_number() over (partition by ml.blockid order by Ml.Hid desc) as rownumber,
  H.HNAME 
from MIT_LeadBechmarkHamletwise ML
join [MT.HAMLE] h on ML.Hid=h.HID

2

Wenn Sie dafür unbedingt ROW_NUMBER verwenden möchten (anstelle von count (*)), können Sie immer Folgendes verwenden:

SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)   
FROM USERS  
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC

2

Sie können das Row_NumberErgebnis der Abfrage begrenzen.

Beispiel:

SELECT * FROM (
    select row_number() OVER (order by createtime desc) AS ROWINDEX,* 
    from TABLENAME ) TB
WHERE TB.ROWINDEX between 0 and 10

- Mit der obigen Abfrage erhalte ich SEITE 1 der Ergebnisse von TABLENAME.


2

Müssen Sie eine virtuelle Tabelle mithilfe von erstellen WITH table AS, was in der angegebenen Abfrage erwähnt wird.

Mithilfe dieser virtuellen Tabelle können Sie die CRUD-Operation wrt ausführen row_number.

ABFRAGE:

WITH table AS
-
(SELECT row_number() OVER(ORDER BY UserId) rn, * FROM Users)
-
SELECT * FROM table WHERE UserName='Joe'
-

Sie können verwenden INSERT, UPDATEoder DELETEim letzten Satz von trotz SELECT.


0

Die SQL-Funktion Row_Number () dient zum Sortieren und Zuweisen einer Bestellnummer zu Datenzeilen im zugehörigen Datensatz. So wird es verwendet, um Zeilen zu nummerieren, zum Beispiel um die Top 10 Zeilen mit dem höchsten Bestellbetrag zu identifizieren oder um die Bestellung jedes Kunden mit dem höchsten Bestellbetrag zu identifizieren usw.

Wenn Sie das Dataset sortieren und jede Zeile nummerieren möchten, indem Sie sie in Kategorien aufteilen, verwenden wir Row_Number () mit Partition By-Klausel. Zum Beispiel das Sortieren von Bestellungen jedes Kunden in sich selbst, wobei der Datensatz alle Bestellungen usw. enthält.

SELECT
    SalesOrderNumber,
    CustomerId,
    SubTotal,
    ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY SubTotal DESC) rn
FROM Sales.SalesOrderHeader

Aber so wie ich es verstehe, möchten Sie die Anzahl der Zeilen berechnen, die durch eine Spalte gruppiert sind. Um die Anforderung zu visualisieren, können Sie die Aggregationsfunktion COUNT () mit der Partition By-Klausel verwenden , wenn Sie die Anzahl aller Bestellungen des zugehörigen Kunden als separate Spalte neben den Bestellinformationen anzeigen möchten

Beispielsweise,

SELECT
    SalesOrderNumber,
    CustomerId,
    COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader

0

Diese Abfrage:

SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'

gibt alle Zeilen zurück, in denen das UserNameist, 'Joe'WENN Sie keine habenUserName='Joe'

Sie werden in der Reihenfolge von aufgelistet UserIDund das row_numberFeld beginnt mit 1 und erhöht sich, wie viele Zeilen auch immer enthaltenUserName='Joe'

Wenn es für Sie nicht funktioniert, hat Ihr WHEREBefehl ein Problem ODER es ist kein UserIDin der Tabelle. Überprüfen Sie die Rechtschreibung für beide Felder UserIDund UserName.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.