Row_number के साथ SQL अपडेट ()


113

मैं एक वृद्धिशील संख्या के साथ अपने कॉलम CODE_DEST को अपडेट करना चाहता हूं। मेरे पास है:

CODE_DEST   RS_NOM
null        qsdf
null        sdfqsdfqsdf
null        qsdfqsdf

मैं इसे अद्यतन करना चाहूंगा:

CODE_DEST   RS_NOM
1           qsdf
2           sdfqsdfqsdf
3           qsdfqsdf

मैंने इस कोड की कोशिश की है:

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

इस वजह से काम नहीं करता है )

मैंने भी कोशिश की है:

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

लेकिन यह भी संघ के कारण काम नहीं करता है।

ROW_NUMBER()SQL Server 2008 R2 में फ़ंक्शन का उपयोग करके मैं किसी कॉलम को कैसे अपडेट कर सकता हूं ?


नमूना डेटा और अपेक्षित परिणाम पोस्ट करें, जो कि SQL उत्तर प्राप्त करने का सबसे अच्छा तरीका है। नहीं तो आपका? कोई मतलब नहीं है और इस तरह जवाब देंगेUPDATE myCol = myCol+1 FROM MyTable WHERE ID=@MyID
जोन्ह

जवाबों:


189

एक और विकल्प

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

क्या यह एक शानदार जवाब है, या यह शानदार है कि SQL सर्वर नेस्टेड SELECT में अपडेट कर सकता है? मुझे लगता है कि दोनों हैं ....
बिज्जी

आप WHERE क्लॉज़ (इसके आधार पर मेरा उत्तर देखें) के साथ भविष्य के अद्यतन प्रदर्शन में बड़े पैमाने पर सुधार कर सकते हैं
साइमन_वेअर

72
DECLARE @id INT 
SET @id = 0 
UPDATE DESTINATAIRE_TEMP
SET @id = CODE_DEST = @id + 1 
GO 

इसे इस्तेमाल करे

http://www.mssqltips.com/sqlservertip/1467/populate-a-sql-server-column-with-a-sequential-number-not-using-an-identity/


2
SQL सर्वर 2012 में मेरे लिए काम करने वाले उपरोक्त में से केवल एक
Anya Hope

11
अच्छा उत्तर! कोशिश: SET CODE_DEST = @id, @id = @id + 1पठनीयता के लिए।
R. Oosterholt

46
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

3
यह तभी काम करता है यदि स्तंभ RS_NOM में मान अद्वितीय हैं, है न? मुझे संदेह है कि यह माना जा सकता है।
टॉबी

17

आपका दूसरा प्रयास मुख्य रूप से विफल रहा क्योंकि आपने सीटीई को अंतर्निहित तालिका के रूप में नामित किया था और सीटीई को ऐसा लगता था मानो यह एक पुनरावर्ती सीटीई था , क्योंकि यह अनिवार्य रूप से स्वयं को संदर्भित करता है। एक पुनरावर्ती CTE में एक विशिष्ट संरचना होनी चाहिए जिसके लिए UNION ALLसेट ऑपरेटर के उपयोग की आवश्यकता होती है ।

इसके बजाय, आप CTE को एक अलग नाम देने के साथ-साथ इसमें लक्ष्य स्तंभ भी जोड़ सकते हैं:

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

16

यह @ एलेक्ज़ेंडर फेडोरेंको के उत्तर का एक संशोधित संस्करण है जिसमें 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

WHERE क्लॉज जोड़कर मैंने पाया कि बाद के अपडेट के लिए प्रदर्शन में व्यापक सुधार हुआ है। Sql Server पंक्ति को अद्यतन करने के लिए लगता है भले ही मान पहले से मौजूद है और ऐसा करने में समय लगता है, इसलिए जहां क्लॉज को जोड़ता है वह उन पंक्तियों पर छोड़ देता है जहां मान परिवर्तित नहीं हुआ है। मुझे कहना है कि मैं चकित था कि यह कितनी तेजी से मेरी क्वेरी चला सकता है।

डिस्क्लेमर: मैं कोई डीबी विशेषज्ञ नहीं हूं, और मैं अपने क्लाज के लिए पार्टिशन बाय का उपयोग कर रहा हूं, इसलिए यह इस क्वेरी के लिए बिल्कुल समान परिणाम नहीं हो सकता है। मेरे लिए विचाराधीन कॉलम एक ग्राहक का भुगतान किया गया आदेश है, इसलिए यह सेट होने के बाद मूल्य आम तौर पर नहीं बदलता है।

यह भी सुनिश्चित करें कि आपके पास अनुक्रमित हैं, खासकर यदि आपके पास SELECT स्टेटमेंट पर WHERE क्लॉज है। एक फ़िल्टर किए गए इंडेक्स ने मेरे लिए बहुत अच्छा काम किया क्योंकि मैं भुगतान स्थितियों के आधार पर फ़िल्टरिंग कर रहा था।


द्वारा मेरी पार्टी का उपयोग कर क्वेरी

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

यदि स्तंभ अशक्त नहीं है, तो 'IS NOT NULL' भाग की आवश्यकता नहीं है।


जब मैं कहता हूं कि प्रदर्शन में वृद्धि बड़े पैमाने पर हुई थी, तो मेरा मतलब था कि छोटी संख्या में पंक्तियों को अपडेट करते समय यह अनिवार्य रूप से तात्कालिक था। सही इंडेक्स के साथ मैं एक ऐसा अपडेट प्राप्त करने में सक्षम था, जो 'इनर' क्वेरी के समान समय लेता है:

  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

@AleksandrFedorenko ईमानदार होने के लिए मैं आश्चर्यचकित था कि यह काम किया है, लेकिन खुशी है कि यह किया :) अनुक्रमित महत्वपूर्ण थे कि मैंने भी बनाया
शमौन_वेर

1
इस उपयोगी टिप के लिए धन्यवाद। सादर।
सेदत कुमकु

3

मैंने अपनी स्थिति के लिए ऐसा किया और काम किया

WITH myUpdate (id, myRowNumber )
AS
( 
    SELECT id, ROW_NUMBER() over (order by ID) As myRowNumber
    FROM AspNetUsers
    WHERE  UserType='Customer' 
 )

update AspNetUsers set EmployeeCode = FORMAT(myRowNumber,'00000#') 
FROM myUpdate
    left join AspNetUsers u on u.Id=myUpdate.id

1

कर्सर को अपडेट करने का सरल और आसान तरीका

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

1

यदि तालिका का संबंध नहीं है, तो बस पंक्ति संख्या के साथ नई तालिका में सभी कॉपी करें और पुराने को हटा दें और पुराने के साथ नया नाम बदलें।

Select   RowNum = ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) , * INTO cdm.dbo.SALES2018 from 
(
select * from SALE2018) as SalesSource
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.