Jak używać ROW_NUMBER ()?

175

Chcę użyć, ROW_NUMBER()aby ...

  1. Aby uzyskać max(ROW_NUMBER())-> Albo przypuszczam, że będzie to również liczba wszystkich wierszy

Próbowałem zrobić:

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

ale wydawało się, że nie działa ...

  1. Aby ROW_NUMBER()skorzystać z danej informacji, tj. jeśli mam imię i chcę wiedzieć, z jakiego wiersza pochodzi nazwa.

Zakładam, że byłoby to coś podobnego do tego, co próbowałem dla nr 1

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

ale to też nie zadziałało ...

Jakieś pomysły?

wydający
źródło

Odpowiedzi:

150

Na pierwsze pytanie, dlaczego po prostu nie użyć?

SELECT COUNT(*) FROM myTable 

aby policzyć.

A jeśli chodzi o drugie pytanie, klucz podstawowy wiersza jest tym, czego należy użyć do zidentyfikowania określonego wiersza. Nie próbuj używać do tego numeru wiersza.


Jeśli w głównym zapytaniu zwróciłeś Row_Number (),

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

Następnie, jeśli chcesz cofnąć się o 5 wierszy, możesz wziąć bieżący numer wiersza i użyć następującego zapytania, aby określić wiersz z bieżącym wierszem -5

SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
     FROM User ) us 
WHERE Row = CurrentRow - 5   
Darrel Miller
źródło
W mojej sytuacji otrzymuję UserId i chcę uzyskać UserId, czyli określoną liczbę wierszy wstecz. Co się stanie, jeśli wiersz zostanie usunięty? W takim przypadku nie mogę po prostu przejść do UserId - offset, ponieważ wtedy nie uzyskałbym właściwego rekordu.
Lepiej jest użyć funkcji select count (1) z mytable, aby wybrać liczbę rekordów. To takie szybkie i wydajne
Sivajith
46

Chociaż zgadzam się z innymi, że możesz użyć, count()aby uzyskać całkowitą liczbę wierszy, oto jak możesz użyć row_count():

  1. Aby uzyskać całkowitą liczbę wierszy:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp
  2. Aby uzyskać numery wierszy, których imię to 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'

Możesz dalej użyć min(rownum)lub, max(rownum)aby uzyskać odpowiednio pierwszy lub ostatni wiersz dla Matta.

Były to bardzo proste implementacje row_number(). Możesz go użyć do bardziej złożonego grupowania. Sprawdź moją odpowiedź na temat grupowania zaawansowanego bez użycia zapytania podrzędnego

Użytkownik SO
źródło
Czy mógłbyś wyjaśnić, jak wybrać kolumnę używaną w order by X? Innymi słowy, jak należy Xokreślić? Dzięki!
Kevin Meredith
@KevinMeredith: To order by Xkolejność, w której będziesz określać kolejność, w jakiej zostaną przypisane wiersze ROW_NUMBERS(). Pamiętaj, że tabele w relacyjnych bazach danych, pomimo ich nazwy, nie mają formalnej kolejności, więc jeśli chcesz wywołać wiersz „1”, „10” lub „1337”, musisz najpierw zamówić je za pomocą ORDER BYklauzuli, która jest tym, który znajduje się w OVER (ORDER BY X)klauzuli.
Wtrmute,
25

Jeśli chcesz zwrócić całkowitą liczbę wierszy w tabeli, możesz użyć alternatywnego sposobu dla SELECT COUNT(*)instrukcji.

Ponieważ SELECT COUNT(*)wykonuje pełne skanowanie tabeli, aby zwrócić liczbę wierszy, w przypadku dużej tabeli może to zająć bardzo dużo czasu. W takim przypadku możesz użyć sysindexestabeli systemowej. Istnieje ROWSkolumna zawierająca całkowitą liczbę wierszy dla każdej tabeli w bazie danych. Możesz użyć następującej instrukcji select:

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

To znacznie skróci czas trwania zapytania.

Muhammad Akhtar
źródło
Masz rację co do pełnego skanowania tabeli, ale pamiętaj, że niekoniecznie jest to skanowanie indeksu klastrowego, ponieważ może do tego użyć indeksu nieklastrowego
yoel halb
2
Jest to również prawdziwe tylko dla Sql-Server, ponieważ inne RDMBS zoptymalizowały liczbę
wyborów
7

ROW_NUMBER() zwraca unikalną liczbę dla każdego wiersza zaczynającego się od 1. Możesz z łatwością tego użyć, pisząc po prostu:

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

Można zobaczyć różnicę między czasem Row_number(), Rank()i Dense_Rank() tu .

Jatin Phulera
źródło
7

Możesz użyć tego do pobrania pierwszego rekordu, gdzie ma klauzulę

SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum 
FROM     Users 
WHERE    UserName = 'Joe'
ORDER BY rownum ASC
Omid Farvid
źródło
4
SELECT num, UserName FROM 
 (SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
  From Users) AS numbered
WHERE UserName='Joe'
Alex Martelli
źródło
Aby wyliczyć wszystkie wiersze - w przeciwnym razie wystarczy wyliczyć wiersze, w których nazwa użytkownika to Joe, co nie jest celem ;-).
Alex Martelli
1
@Matt: Nazwij mnie pedantem; Preferuję raczej „tabelę pochodną” lub „widok anonimowy” od terminu „wybór podrzędny”.
Mechanical_meat
1
@adam, bo ja też jestem pedantem - czy „zagnieżdżony wybór” uczyniłby Cię szczęśliwszym? Nie lubię używać terminów takich jak tabela lub widok, gdy w pobliżu nie ma słowa kluczowego TABLElub VIEWsłowa kluczowego ... ale na SELECTpewno! -)
Alex Martelli
@Alex: przedstawiasz ważny punkt. „Zagnieżdżony wybór” działa świetnie :) Przy okazji, bardzo lubię czytać anegdoty, które dodajesz do swoich komentarzy i odpowiedzi.
Mechanical_meat
@Adam, dzięki! Czasami moje odpowiedzi są bardzo czystym kodem, jak tutaj, ale uwielbiam je rozwijać, gdy mam wolną chwilę ;-).
Alex Martelli
4

Może nie mieć związku z tym pytaniem. Ale odkryłem, że może być przydatny podczas używania ROW_NUMBER-

SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID 
FROM #Any_Table
Jyo
źródło
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
Hari Lakkakula
źródło
2

Jeśli absolutnie chcesz użyć w tym celu ROW_NUMBER (zamiast count (*)), zawsze możesz użyć:

SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)   
FROM USERS  
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC
Richard S.
źródło
2

Możesz użyć Row_Numberdo ograniczenia wyniku zapytania.

Przykład:

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

- Przy powyższym zapytaniu otrzymam STRONĘ 1 wyników z TABLENAME.

Johnson Pham
źródło
2

Trzeba stworzyć wirtualną tabelę za pomocą WITH table AS, o której wspomina się w danym zapytaniu.

Korzystając z tej tabeli wirtualnej, można wykonać operację CRUD wrt row_number.

PYTANIE:

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

Możesz użyć INSERT, UPDATElub DELETEw ostatnim zdaniu przez pomimo SELECT.

Gaurav Chutke
źródło
0

Funkcja SQL Row_Number () służy do sortowania i przypisywania numeru zamówienia do wierszy danych w powiązanym zestawie rekordów. Jest więc używany do numerowania wierszy, na przykład do identyfikowania pierwszych 10 wierszy, które mają najwyższą kwotę zamówienia lub do identyfikowania zamówienia każdego klienta, które jest najwyższą kwotą itp.

Jeśli chcesz posortować zbiór danych i ponumerować każdy wiersz, rozdzielając je na kategorie, używamy Row_Number () z klauzulą ​​Partition By. Na przykład sortowanie zamówień każdego klienta w sobie, gdzie zestaw danych zawiera wszystkie zamówienia itp.

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

Ale jak rozumiem, chcesz obliczyć liczbę wierszy pogrupowanych według kolumny. Aby zwizualizować wymaganie, jeśli chcesz zobaczyć liczbę wszystkich zamówień powiązanego klienta jako oddzielną kolumnę oprócz informacji o zamówieniu, możesz użyć funkcji agregującej COUNT () z klauzulą ​​Partition By

Na przykład,

SELECT
    SalesOrderNumber,
    CustomerId,
    COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader
Eralper
źródło
0

To zapytanie:

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

zwróci wszystkie wiersze, w których UserNamejest, 'Joe'JEŚLI nie maszUserName='Joe'

Zostaną wyświetlone w kolejności, UserIDa row_numberpole będzie rozpoczynać się od 1 i zwiększać się niezależnie od liczby wierszyUserName='Joe'

Jeśli to nie zadziała, oznacza to, że WHEREwystąpił problem z Twoim poleceniem LUB nie ma go UserIDw tabeli. Sprawdź pisownię w obu polach UserIDi UserName.

Clark Vera
źródło