Como uso ROW_NUMBER ()?

175

Eu quero usar o ROW_NUMBER()para obter ...

  1. Para obter o max(ROW_NUMBER())-> Ou eu acho que isso também seria a contagem de todas as linhas

Eu tentei fazer:

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

mas não parecia funcionar ...

  1. Para ROW_NUMBER()usar uma determinada informação, ie. se eu tenho um nome e quero saber de que linha o nome veio.

Suponho que seria algo semelhante ao que eu tentei para # 1

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

mas isso também não funcionou ...

Alguma ideia?

gastador
fonte

Respostas:

150

Para a primeira pergunta, por que não usar?

SELECT COUNT(*) FROM myTable 

para obter a contagem.

E para a segunda pergunta, a chave primária da linha é o que deve ser usado para identificar uma linha específica. Não tente usar o número da linha para isso.


Se você retornou Row_Number () na sua consulta principal,

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

Então, quando você quiser voltar 5 linhas, poderá pegar o número da linha atual e usar a consulta a seguir para determinar a linha com currentrow -5

SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
     FROM User ) us 
WHERE Row = CurrentRow - 5   
Darrel Miller
fonte
Na minha situação, recebi um UserId e quero obter o UserId com um certo número de linhas de volta. E se uma linha for excluída? Nesse caso, não posso simplesmente compensar o UserId - porque não conseguiria o registro certo.
É melhor usar select count (1) da mytable para selecionar a contagem de registros. Este modo rápido e eficiente
Sivajith
46

Embora eu concorde com outras pessoas que você pode usar count()para obter o número total de linhas, eis como você pode usar o row_count():

  1. Para obter o número total de linhas:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp
  2. Para obter os números de linha em que nome é 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'

Você pode usar ainda mais min(rownum)ou max(rownum)obter a primeira ou a última linha de Matt, respectivamente.

Estas foram implementações muito simples de row_number(). Você pode usá-lo para agrupamentos mais complexos. Confira minha resposta no agrupamento avançado sem usar uma subconsulta

Usuário SO
fonte
Você poderia explicar como escolher a coluna usada order by X? Em outras palavras, como deve Xser determinado? Obrigado!
Kevin Meredith
@KevinMeredith: order by Xé a ordem que você usará para determinar a ordem em que as linhas serão atribuídas ROW_NUMBERS(). Lembre-se de que as tabelas nos bancos de dados relacionais, apesar do nome, não têm uma ordem formal; portanto, se você quiser chamar a linha "1" ou "10" ou "1337", precisará solicitá-las primeiro usando uma ORDER BYcláusula é o que entra na OVER (ORDER BY X)cláusula.
Wtrmute 13/09/17
25

Se você precisar retornar a contagem total de linhas da tabela, poderá usar uma maneira alternativa para a SELECT COUNT(*)instrução

Como SELECT COUNT(*)faz uma varredura completa da tabela para retornar a contagem de linhas, pode levar muito tempo para uma tabela grande. Você pode usar a sysindexestabela do sistema nesse caso. Há uma ROWScoluna que contém a contagem total de linhas para cada tabela no seu banco de dados. Você pode usar a seguinte instrução select:

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

Isso reduzirá drasticamente o tempo que sua consulta leva.

Muhammad Akhtar
fonte
Você está certo sobre a varredura completa da tabela, mas nota que não é necessariamente uma verificação de índice em cluster, como poderia usar um índice não agrupado para isso
halb yoel
2
Também isso é verdade apenas para o SQL-Server, como outros RDMBS têm otimizado a contagem select
halb yoel
7

ROW_NUMBER() retorna um número único para cada linha começando com 1. Você pode usá-lo facilmente, escrevendo:

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

Você pode encontrar a diferença entre Row_number(), Rank()e Dense_Rank() aqui .

Jatin Phulera
fonte
7

Você pode usar isso para obter o primeiro registro where cláusula

SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum 
FROM     Users 
WHERE    UserName = 'Joe'
ORDER BY rownum ASC
Omid Farvid
fonte
4
SELECT num, UserName FROM 
 (SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
  From Users) AS numbered
WHERE UserName='Joe'
Alex Martelli
fonte
Para enumerar todas as linhas - caso contrário, você está apenas enumerando as linhas em que o nome de usuário é Joe, que não é o objetivo ;-).
Alex Martelli
1
@ Matt: Me chame de pedante; Costumo preferir "tabela derivada" ou "exibição anônima" ao termo "sub-seleção".
mechanical_meat
1
@ Adam, como eu também sou um pedante - "seleção aninhada" faria você mais feliz? Eu não gosto de termos de uso, como tabela ou exibição quando nenhuma TABLEou VIEWpalavra-chave é em torno ... mas SELECTcom certeza é! -)
Alex Martelli
@ Alex: você apresenta um ponto válido. "Seleção aninhada" funciona muito bem para mim :) A propósito, eu realmente gosto de ler as anedotas que você adiciona aos seus comentários e respostas.
mechanical_meat
@ Adam, obrigado! Às vezes, minhas respostas são um código muito simples, como aqui, mas eu gosto de realizá-las quando tenho um minuto livre ;-).
Alex Martelli
4

Pode não estar relacionado à pergunta aqui. Mas achei que poderia ser útil ao usar ROW_NUMBER-

SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID 
FROM #Any_Table
Jyo
fonte
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
fonte
2

Se você deseja absolutamente usar ROW_NUMBER para isso (em vez de contar (*)), sempre pode usar:

SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)   
FROM USERS  
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC
Richard S
fonte
2

Você pode usar Row_Numberpara limitar o resultado da consulta.

Exemplo:

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

- Com a consulta acima, receberei a PÁGINA 1 dos resultados TABLENAME.

Johnson Pham
fonte
2

Precisa criar uma tabela virtual usando WITH table AS, mencionado na Consulta especificada.

Usando esta tabela virtual, você pode executar a operação CRUD row_number.

INQUERIR:

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

Você pode usar INSERT, UPDATEou DELETEna última frase, apesar de SELECT.

Gaurav Chutke
fonte
0

A função SQL Row_Number () é para classificar e atribuir um número de pedido às linhas de dados no conjunto de registros relacionados. Por isso, é usado para numerar linhas, por exemplo, para identificar as 10 principais linhas com o maior valor de pedido ou identificar o pedido de cada cliente com o maior valor, etc.

Se você deseja classificar o conjunto de dados e numerar cada linha, separando-os em categorias, usamos Row_Number () com a cláusula Partition By. Por exemplo, classificando pedidos de cada cliente dentro de si onde o conjunto de dados contém todos os pedidos, etc.

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

Mas, pelo que entendi, você deseja calcular o número de linhas agrupadas por uma coluna. Para visualizar o requisito, se você deseja ver a contagem de todos os pedidos do cliente relacionado como uma coluna separada, além das informações do pedido, é possível usar a função de agregação COUNT () com a cláusula Partition By

Por exemplo,

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

Esta consulta:

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

retorna todas as linhas onde o UserNameé 'Joe'menos que você não temUserName='Joe'

Eles serão listados em ordem de UserIDe o row_numbercampo começará com 1 e será incrementado, no entanto, muitas linhas contêmUserName='Joe'

Se não funcionar, seu WHEREcomando tem um problema OU não existe UserIDna tabela. Verifique a ortografia para ambos os campos UserIDe UserName.

Clark Vera
fonte