tags:

views:

64

answers:

4

Hi,

I would like to know if there is a way to use an order by clause when updating a table. I am updating a table and setting a consecutive number, that's why the order of the update is important. Using the following sql statement, I was able to solve it without using a cursor:

DECLARE @Number INT = 0

UPDATE Test
SET @Number = Number = @Number +1

now what I'd like to to do is an order by clause like so:

 DECLARE @Number INT = 0

 UPDATE Test
 SET @Number = Number = @Number +1
 ORDER BY Test.Id DESC

I've read: http://stackoverflow.com/questions/655010/how-to-update-and-order-by-using-ms-sql The solutions to this question do not solve the ordering problem - they just filter the items on which the update is applied.

Take care, Martin

+2  A: 

You can not use ORDER BY as part of the UPDATE statement (you can use in sub-selects that are part of the update).

UPDATE Test 
SET Number = rowNumber 
FROM Test
INNER JOIN 
(SELECT ID, row_number() OVER (ORDER BY ID DESC) as rowNumber
FROM Test) drRowNumbers ON drRowNumbers.ID = Test.ID
Mitch Wheat
+2  A: 

No.

Not a documented 100% supported way. There is an approach sometimes used for calculating running totals called "quirky update" that suggests that it might update in order of clustered index if certain conditions are met but as far as I know this relies completely on empirical observation rather than any guarantee.

But what version of SQL Server are you on? If SQL2005+ you might be able to do something with row_number and a CTE (You can update the CTE)

With cte As
(
SELECT id,Number,
ROW_NUMBER() OVER (ORDER BY id DESC) AS RN
FROM Test
)
UPDATE cte SET Number=RN
Martin Smith
+1. The CTE form is nice.
Mitch Wheat
Sure, but we can target lesser versions by using a subquery.
spender
@spender what version supports row_number but not ctes?
Martin Smith
ah. you got me there! ;) I only came into the SqlServer world at 2005, where CTEs were shiny and new. I always thought row_number had been around a little longer.
spender
jerleth
@Martin - Sorry if I wasn't clear. The `Row_number()` approach will give you the correct results for the example in your question. It doesn't rely upon any particular update order. Obviously if your actual needs are a bit different and you are calculating running totals or something this won't be suitable.
Martin Smith
+1  A: 

The row_number() function would be the best approach to this problem.

UPDATE T
    SET T.Number = R.rowNum
    FROM Test T
    JOIN (
        SELECT T2.id,row_number() over (order by T2.Id desc) rowNum from Test T2
    ) R on T.id=R.id 
spender
I couldn't get your solution to work - no matter which way I order the numbers are always assigned in the same direction.
jerleth
The order of assignment of the numbers is assigned by the over clause of row_number (i.e. row_number() over (order by T2.Id desc)). What are you trying?
spender
+1  A: 

Edit

Following solution could have problems with clustered indexes involved as mentioned here. Thanks to Martin for pointing this out.

The answer is kept to educate those (like me) who don't know all side-effects or ins and outs of SQL Server.


Expanding on the answer gaven by Quassnoi in your link, following works

DECLARE @Test TABLE (Number INTEGER, AText VARCHAR(2), ID INTEGER)
DECLARE @Number INT

INSERT INTO @Test VALUES (1, 'A', 1)
INSERT INTO @Test VALUES (2, 'B', 2)
INSERT INTO @Test VALUES (1, 'E', 5)
INSERT INTO @Test VALUES (3, 'C', 3)
INSERT INTO @Test VALUES (2, 'D', 4)

SET @Number = 0

;WITH q AS (
    SELECT  TOP 1000000 *
    FROM    @Test
    ORDER BY
            ID
)            
UPDATE  q
SET     @Number = Number = @Number + 1
Lieven
That probably will work if id is the clustered index but isn't guaranteed to work. See the discussion here http://weblogs.sqlteam.com/mladenp/archive/2009/07/28/SQL-Server-2005-Fast-Running-Totals.aspx
Martin Smith
I have to say, I'm not too keen on the side-effect method of performing updates.
spender
@Martin Smith, thanks for the link. I was thinking about deleting the answer but it might as well stay, if not alone for the link you've provided.
Lieven
@Lieven - You might also be interested in this article http://www.sqlservercentral.com/articles/T-SQL/68467/
Martin Smith