2012-11-30 19 views
67

voglio aggiornare la mia colonna CODE_DEST con un numero incrementale. Ho:Aggiornamento SQL con row_number()

CODE_DEST RS_NOM 
null  qsdf 
null  sdfqsdfqsdf 
null  qsdfqsdf 

Vorrei aggiornare per essere:

CODE_DEST RS_NOM 
1   qsdf 
2   sdfqsdfqsdf 
3   qsdfqsdf 

Ho provato questo codice:

UPDATE DESTINATAIRE_TEMP 
SET CODE_DEST = TheId 
FROM (SELECT Row_Number() OVER (ORDER BY [RS_NOM]) AS TheId FROM DESTINATAIRE_TEMP) 

Questo non funziona a causa della )

ho anche provato:

WITH DESTINATAIRE_TEMP AS 
    (
    SELECT 
    ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN 
    FROM DESTINATAIRE_TEMP 
) 
UPDATE DESTINATAIRE_TEMP SET CODE_DEST=RN 

Ma anche questo non funziona a causa di unione.

Come posso aggiornare una colonna utilizzando la funzione ROW_NUMBER() in SQL Server 2008 R2?

+0

Dati post di esempio e dei risultati attesi, che è il modo migliore per ottenere uno SQL rispondere con Altrimenti tuo? non ha senso e produrrà risposte come questa 'UPDATE myCol = myCol + 1 FROM MyTable WHERE ID = @ MyID' – JonH

risposta

33
With UpdateData As 
(
SELECT RS_NOM, 
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN 
FROM DESTINATAIRE_TEMP 
) 
UPDATE DESTINATAIRE_TEMP SET CODE_DEST = RN 
FROM DESTINATAIRE_TEMP 
INNER JOIN UpdateData ON DESTINATAIRE_TEMP.RS_NOM = UpdateData.RS_NOM 
+1

Questo funziona solo se i valori nella colonna RS_NOM sono univoci, non è vero? Dubito che questo possa essere assunto. – Toby

112

Un'altra opzione

UPDATE x 
SET x.CODE_DEST = x.New_CODE_DEST 
FROM (
     SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST 
     FROM DESTINATAIRE_TEMP 
    ) x 
+0

Confusione, si hanno due variabili denominate x. Rinominare la prima variabile e modificare la risposta per favore. – Craig

+14

@Craig: cosa intendi per "due variabili denominate x"? Questa istruzione UPDATE non fa riferimento a nessuna variabile. C'è solo una cosa chiamata * x * in questa soluzione ed è la tabella derivata definita nella clausola FROM. Niente è ambiguo qui. Forse la sintassi non ti è familiare, ma va bene, puoi solo spiegare ciò che consideri confuso e spero di ottenere una risposta che chiarisca la tua confusione (nel caso in cui il manuale non aiuti). –

+0

Questa è una risposta brillante o è geniale che SQL Server possa aggiornare all'interno di uno SELECT nidificato? Penso che entrambi siano ... – Bigjim

10

tuo secondo tentativo fallì soprattutto perché avete chiamato i CTE stessa tabella sottostante e fatto la CTE sguardo come se fosse un CTE ricorsiva, perché essenzialmente riferito a se stesso. Un recursive CTE deve avere una struttura specifica che richiede l'utilizzo dell'operatore UNION ALL impostato.

Invece, si può solo avere dato il CTE un nome diverso, così come ha aggiunto la colonna di destinazione ad esso:

With SomeName As 
(
SELECT 
CODE_DEST, 
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN 
FROM DESTINATAIRE_TEMP 
) 
UPDATE SomeName SET CODE_DEST=RN 
0

modo semplice e veloce per aggiornare il cursore

UPDATE Cursor 
SET Cursor.CODE = Cursor.New_CODE 
FROM (
    SELECT CODE, ROW_NUMBER() OVER (ORDER BY [CODE]) AS New_CODE 
    FROM Table Where CODE BETWEEN 1000 AND 1999 
) Cursor 
6

Si tratta di una versione modificata della risposta di @Aleksandr Fedorenko aggiungere una clausola WHERE:

UPDATE x 
SET x.CODE_DEST = x.New_CODE_DEST 
FROM (
     SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST 
     FROM DESTINATAIRE_TEMP 
    ) x 
WHERE x.CODE_DEST <> x.New_CODE_DEST AND x.CODE_DEST IS NOT NULL 

Con l'aggiunta di una clausola dove ho trovato le prestazioni migliorate in maniera massiccia per gli aggiornamenti successivi. Sql Server sembra aggiornare la riga anche se il valore esiste già e ci vuole del tempo per farlo, quindi aggiungere la clausola where lo fa saltare le righe in cui il valore non è cambiato. Devo dire che sono rimasto sbalordito dalla velocità con cui poteva eseguire la mia interrogazione.

Disclaimer: io non sono un esperto di DB, e sto usando PARTITION BY per la mia clausola in modo che non può essere esattamente gli stessi risultati di questa ricerca. Per me la colonna in questione è l'ordine pagato di un cliente, quindi il valore generalmente non cambia una volta impostato.

Inoltre, assicurarsi di avere indici, soprattutto se si dispone di una clausola WHERE sul SELECT. Un indice filtrato ha funzionato perfettamente per me poiché stavo filtrando in base agli stati dei pagamenti.


mio query utilizzando partizione

UPDATE UpdateTarget 
SET  PaidOrderIndex = New_PaidOrderIndex 
FROM 
(
    SELECT PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex 
    FROM [Order] 
    WHERE PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null 
) AS UpdateTarget 

WHERE UpdateTarget.PaidOrderIndex <> UpdateTarget.New_PaidOrderIndex AND UpdateTarget.PaidOrderIndex IS NOT NULL 

-- test to 'break' some of the rows, and then run the UPDATE again 
update [order] set PaidOrderIndex = 2 where PaidOrderIndex=3 

Il 'non è nullo' parte non è necessaria se la colonna non è annullabile.


quando dico l'incremento di prestazioni era enorme intendo dire che era essenzialmente istantanei quando si aggiorna un piccolo numero di righe. Con gli indici di destra sono stato in grado di ottenere un aggiornamento che ha preso la stessa quantità di tempo come la query 'interna' fa da sé:

SELECT PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex 
    FROM [Order] 
    WHERE PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null 
+1

Questo è un punto molto interessante. Grazie –

+0

@AleksandrFedorenko ad essere onesti, sono rimasto sorpreso che abbia funzionato, ma contento di averlo fatto :) gli indici erano importanti che ho creato anch'io –

Problemi correlati