Come posso usare ROW_NUMBER ()?


175

Voglio usare il ROW_NUMBER()per ottenere ...

  1. Per ottenere il max(ROW_NUMBER())-> O suppongo che questo sarebbe anche il conteggio di tutte le righe

Ho provato a fare:

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

ma non sembra funzionare ...

  1. Per ROW_NUMBER()utilizzare una determinata informazione, ad es. se ho un nome e voglio sapere da quale riga proviene il nome.

Presumo che sarebbe qualcosa di simile a quello che ho provato per il n. 1

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

ma neanche questo ha funzionato ...

Qualche idea?

Risposte:


151

Per la prima domanda, perché non usare solo?

SELECT COUNT(*) FROM myTable 

per ottenere il conteggio.

E per la seconda domanda, la chiave primaria della riga è cosa dovrebbe essere usato per identificare una particolare riga. Non provare a usare il numero di riga per quello.


Se hai restituito Row_Number () nella tua query principale,

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

Quindi, quando si desidera tornare indietro di 5 righe, è possibile prendere il numero di riga corrente e utilizzare la query seguente per determinare la riga con currentrow -5

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

Nella mia situazione mi viene dato un ID utente e desidero ottenere l'Usid che è un certo numero di righe indietro. Cosa succede se una riga viene eliminata? In tal caso, non posso semplicemente usare UserId - offset, perché non otterrei il record giusto.

È meglio usare select count (1) da mytable per selezionare il conteggio dei record. Questo così rapido ed efficiente
Sivajith il

46

Anche se sono d'accordo con gli altri che potresti utilizzare count()per ottenere il numero totale di righe, ecco come puoi utilizzare row_count():

  1. Per ottenere il numero totale di righe:

    with temp as (
        select row_number() over (order by id) as rownum
        from table_name 
    )
    select max(rownum) from temp
  2. Per ottenere i numeri di riga in cui il 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'

È inoltre possibile utilizzare min(rownum)o max(rownum)per ottenere rispettivamente la prima o l'ultima riga per Matt.

Queste erano implementazioni molto semplici di row_number(). Puoi usarlo per raggruppamenti più complessi. Dai un'occhiata alla mia risposta sul raggruppamento avanzato senza utilizzare una query secondaria


Potresti spiegare come scegliere la colonna, utilizzata in order by X? In altre parole, come dovrebbe Xessere determinato? Grazie!
Kevin Meredith,

@KevinMeredith: order by Xè l'ordine che utilizzerai per determinare l'ordine in cui verranno assegnate le righe ROW_NUMBERS(). Ricorda che le tabelle nei database relazionali, nonostante il loro nome, non hanno un ordinamento formale, quindi se vuoi chiamare una riga "1" o "10" o "1337", devi prima ordinarle usando una ORDER BYclausola, che è quello che va nella OVER (ORDER BY X)clausola.
Wtrmute,

25

Se è necessario restituire il conteggio totale delle righe della tabella, è possibile utilizzare un modo alternativo SELECT COUNT(*)all'istruzione.

Poiché SELECT COUNT(*)esegue una scansione completa della tabella per restituire il conteggio delle righe, potrebbe essere necessario molto tempo per una tabella di grandi dimensioni. In sysindexesquesto caso è possibile utilizzare la tabella di sistema. C'è una ROWScolonna che contiene il conteggio totale delle righe per ogni tabella nel database. È possibile utilizzare la seguente istruzione select:

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

Ciò ridurrà drasticamente il tempo impiegato dalla query.


Hai ragione riguardo alla scansione completa della tabella, ma tieni presente che non è necessariamente una scansione di indice cluster, poiché potrebbe utilizzare un indice non cluster per quello
yoel halb

2
Anche questo vale solo per Sql-Server, poiché altri RDMBS hanno ottimizzato il conteggio selezionato
yoel halb

7

ROW_NUMBER() restituisce un numero univoco per ogni riga che inizia con 1. Puoi facilmente usarlo semplicemente scrivendo:

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

È possibile calcolare la differenza tra Row_number(), Rank()e Dense_Rank() qui .


7

Puoi usarlo per ottenere il primo record in cui ha la clausola

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'

Per enumerare tutte le righe - altrimenti stai semplicemente enumerando le righe in cui lo username è Joe, che non è l'obiettivo ;-).
Alex Martelli,

1
@Matt: chiamami pedante; Tendo a preferire "tabella derivata" o "vista anonima" al termine "selezione secondaria".
Mechanical_meat

1
@adam, visto che anch'io sono un pedante, "la selezione nidificata" ti renderebbe più felice? Non mi piace usare termini come tabella o vista quando non ci sono parole chiave TABLEo no VIEW... ma SELECTsicuramente lo è! -)
Alex Martelli,

@Alex: presenti un punto valido. "Selezione nidificata" funziona alla grande per me :) A proposito, mi piace molto leggere gli aneddoti che aggiungi ai tuoi commenti e risposte.
Mechanical_meat

@Adam, grazie! A volte le mie risposte sono un codice molto spoglio, come qui, ma adoro darle un tocco in più quando ho un minuto libero ;-).
Alex Martelli,

4

Non può essere correlato alla domanda qui. Ma ho scoperto che potrebbe essere utile quando si utilizza 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

Se vuoi assolutamente usare ROW_NUMBER per questo (invece del conteggio (*)) puoi sempre usare:

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

2

È possibile utilizzare Row_Numberper il risultato della query limite.

Esempio:

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

- Con la query sopra, otterrò la PAGINA 1 dei risultati da TABLENAME.


2

È necessario creare una tabella virtuale utilizzando WITH table AS, che è menzionato in una determinata query.

Utilizzando questa tabella virtuale, è possibile eseguire l'operazione CRUD wrt row_number.

DOMANDA:

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

Puoi usare INSERT, UPDATEo DELETEnell'ultima frase, nonostante SELECT.


0

La funzione SQL Row_Number () consiste nell'ordinare e assegnare un numero d'ordine alle righe di dati nel set di record correlato. Quindi viene utilizzato per numerare le righe, ad esempio per identificare le prime 10 righe che hanno l'importo dell'ordine più elevato o identificare l'ordine di ciascun cliente che è l'importo più elevato, ecc.

Se desideri ordinare il set di dati e numerare ogni riga separandoli in categorie, utilizziamo Row_Number () con la clausola Partition By. Ad esempio, l'ordinamento degli ordini di ciascun cliente all'interno di se stesso in cui il set di dati contiene tutti gli ordini, ecc.

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

Ma a quanto ho capito, vuoi calcolare il numero di righe raggruppate per colonna. Per visualizzare il requisito, se si desidera visualizzare il conteggio di tutti gli ordini del cliente correlato come colonna separata oltre alle informazioni sull'ordine, è possibile utilizzare funzione di aggregazione COUNT () con la clausola Partition By

Per esempio,

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

0

Questa query:

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

restituirà tutte le righe in cui si UserNametrova'Joe' MENO che tu non abbiaUserName='Joe'

Saranno elencati in ordine di UserIDe ilrow_number campo inizierà con 1 e incrementerà per quanto molte righe contenganoUserName='Joe'

Se non funziona per te, il tuo WHEREcomando ha un problema OPPURE non ce n'è UserIDnella tabella. Controlla l'ortografia per entrambi i campi UserIDe UserName.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.