Comment utiliser ROW_NUMBER ()?

175

Je veux utiliser ROW_NUMBER()pour obtenir ...

  1. Pour obtenir le max(ROW_NUMBER())-> Ou je suppose que ce serait également le nombre de toutes les lignes

J'ai essayé de faire:

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

mais cela ne semblait pas fonctionner ...

  1. Pour obtenir en ROW_NUMBER()utilisant une information donnée, c'est à dire. si j'ai un nom et que je veux savoir de quelle ligne le nom vient.

Je suppose que ce serait quelque chose de similaire à ce que j'ai essayé pour # 1

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

mais cela n'a pas fonctionné non plus ...

Des idées?

dépensier
la source

Réponses:

151

Pour la première question, pourquoi ne pas simplement utiliser?

SELECT COUNT(*) FROM myTable 

pour obtenir le décompte.

Et pour la deuxième question, la clé primaire de la ligne est ce qui doit être utilisé pour identifier une ligne particulière. N'essayez pas d'utiliser le numéro de ligne pour cela.


Si vous avez renvoyé Row_Number () dans votre requête principale,

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

Ensuite, lorsque vous voulez revenir 5 lignes en arrière, vous pouvez prendre le numéro de ligne actuel et utiliser la requête suivante pour déterminer la ligne avec 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
la source
Dans ma situation, on me donne un UserId et je veux récupérer le UserId qui représente un certain nombre de lignes. Que faire si une ligne est supprimée? Dans ce cas, je ne peux pas simplement utiliser UserId - offset, car alors je n'obtiendrais pas le bon enregistrement.
Il est préférable d'utiliser select count (1) de mytable pour sélectionner le nombre d'enregistrements. C'est si rapide et efficace
Sivajith
46

Bien que je sois d'accord avec d'autres que vous pourriez utiliser count()pour obtenir le nombre total de lignes, voici comment vous pouvez utiliser le row_count():

  1. Pour obtenir le nombre total de lignes:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp
  2. Pour obtenir les numéros de ligne où le nom est 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'

Vous pouvez également utiliser min(rownum)ou max(rownum)pour obtenir respectivement la première ou la dernière ligne de Matt.

Il s'agissait d'implémentations très simples de row_number(). Vous pouvez l'utiliser pour des regroupements plus complexes. Consultez ma réponse sur le regroupement avancé sans utiliser de sous-requête

Utilisateur SO
la source
Pourriez-vous expliquer comment choisir la colonne utilisée dans order by X? En d'autres termes, comment doit- Xon déterminer? Merci!
Kevin Meredith
@KevinMeredith: C'est order by Xl'ordre que vous utiliserez pour déterminer l'ordre dans lequel les lignes seront attribuées ROW_NUMBERS(). N'oubliez pas que les tables des bases de données relationnelles, malgré leur nom, n'ont pas d'ordre formel, donc si vous voulez appeler une ligne «1» ou «10» ou «1337», vous devez d'abord les ordonner à l'aide d'une ORDER BYclause, qui est celui qui entre dans l' OVER (ORDER BY X)article.
Wtrmute le
25

Si vous devez renvoyer le nombre total de lignes de la table, vous pouvez utiliser un autre moyen de l' SELECT COUNT(*)instruction.

Dans la mesure où SELECT COUNT(*)une analyse complète de la table renvoie le nombre de lignes, cela peut prendre très longtemps pour une table volumineuse. Vous pouvez utiliser la sysindexestable système à la place dans ce cas. Une ROWScolonne contient le nombre total de lignes pour chaque table de votre base de données. Vous pouvez utiliser l'instruction de sélection suivante:

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

Cela réduira considérablement la durée de votre requête.

Muhammad Akhtar
la source
Vous avez raison sur l'analyse complète de la table, mais notez qu'il ne s'agit pas nécessairement d'une analyse d'index clusterisé, car elle pourrait utiliser un index non clusterisé pour cela
yoel halb
2
De plus, cela n'est vrai que pour Sql-Server, car d'autres RDMBS ont optimisé le nombre de sélections
yoel halb
7

ROW_NUMBER() renvoie un numéro unique pour chaque ligne commençant par 1. Vous pouvez facilement l'utiliser en écrivant simplement:

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

Vous pouvez trouver la différence entre Row_number(), Rank()et Dense_Rank() ici .

Jatin Phulera
la source
7

Vous pouvez l'utiliser pour obtenir le premier enregistrement où a la clause

SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum 
FROM     Users 
WHERE    UserName = 'Joe'
ORDER BY rownum ASC
Omid Farvid
la source
4
SELECT num, UserName FROM 
 (SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
  From Users) AS numbered
WHERE UserName='Joe'
Alex Martelli
la source
Pour énumérer toutes les lignes - sinon vous ne faites qu'énumérer les lignes où le nom d'utilisateur est Joe, ce qui n'est pas le but ;-).
Alex Martelli
1
@Matt: Appelez-moi un pédant; J'ai tendance à préférer "table dérivée" ou "vue anonyme" au terme "sous-sélection".
mechanical_meat
1
@adam, comme je suis aussi un pédant - est-ce que "nested select" vous rendrait plus heureux? Je n'aime pas utiliser des termes tels que table ou vue quand aucun TABLEou VIEWmot-clé est autour ... mais SELECTbien sûr! -)
Alex Martelli
@Alex: vous présentez un point valide. "Sélection imbriquée" fonctionne très bien pour moi :) Au fait, j'aime beaucoup lire les anecdotes que vous ajoutez à vos commentaires et réponses.
mechanical_meat
@Adam, merci! Parfois, mes réponses sont très simples, comme ici, mais j'aime les étoffer quand j'ai une minute de libre ;-).
Alex Martelli
4

Peut ne pas être lié à la question ici. Mais j'ai trouvé que cela pouvait être utile lors de l'utilisation ROW_NUMBER-

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

Si vous voulez absolument utiliser ROW_NUMBER pour cela (au lieu de count (*)), vous pouvez toujours utiliser:

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

Vous pouvez utiliser Row_Numberpour le résultat de la requête de limite.

Exemple:

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

- Avec la requête ci-dessus, j'obtiendrai la PAGE 1 des résultats TABLENAME.

Johnson Pham
la source
2

Besoin de créer une table virtuelle en utilisant WITH table AS, ce qui est mentionné dans une requête donnée.

En utilisant cette table virtuelle, vous pouvez exécuter l'opération CRUD row_number.

REQUETE:

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

Vous pouvez utiliser INSERT, UPDATEou DELETEdans la dernière phrase par malgré SELECT.

Gaurav Chutke
la source
0

La fonction SQL Row_Number () consiste à trier et à attribuer un numéro d'ordre aux lignes de données dans le jeu d'enregistrements associé. Il est donc utilisé pour numéroter les lignes, par exemple pour identifier les 10 premières lignes qui ont le montant de commande le plus élevé ou pour identifier la commande de chaque client qui est le montant le plus élevé, etc.

Si vous souhaitez trier l'ensemble de données et numéroter chaque ligne en les séparant en catégories, nous utilisons Row_Number () avec la clause Partition By. Par exemple, trier les commandes de chaque client en lui-même où l'ensemble de données contient toutes les commandes, etc.

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

Mais si je comprends bien, vous voulez calculer le nombre de lignes de regroupées par une colonne. Pour visualiser l'exigence, si vous souhaitez voir le nombre de toutes les commandes du client associé sous forme de colonne distincte en plus des informations de commande, vous pouvez utiliser la fonction d'agrégation COUNT () avec la clause Partition By

Par exemple,

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

Cette requête:

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

renverra toutes les lignes où le UserNameest 'Joe'sauf si vous n'avez pasUserName='Joe'

Ils seront répertoriés dans l'ordre de UserIDet le row_numberchamp commencera par 1 et augmentera selon le nombre de lignes contenantUserName='Joe'

Si cela ne fonctionne pas pour vous, votre WHEREcommande a un problème OU il n'y UserIDen a pas dans le tableau. Vérifiez l'orthographe des deux champs UserIDet UserName.

Clark Vera
la source