5

Imagine there's a table with the following contents:

 x      y     z
 aa     5     null
 bb     2     null
 cc     5     null
 dd     1     null

I want to sort the rows by y and assign an auto-incremented field to z, so in this case the end result (the changed table) would be

 x      y     z
 dd     1     1
 bb     2     2
 aa     5     3
 cc     5     4

or

 x      y     z
 aa     5     3
 bb     2     2
 cc     5     4
 dd     1     1

How do I do that?

So to make it clear, I want to change the table, not get that stuff to code.

As requested, http://sqlfiddle.com/#!2/cd610/1

6
  • It would be easier for us to help you if you set up a SQL Fiddle Commented Jun 6, 2013 at 17:56
  • you can fiddle with user variables, but usually this kind of thing is more easily & reliably left to application code. Commented Jun 6, 2013 at 18:00
  • @JohnConde, added to body Commented Jun 6, 2013 at 18:02
  • where are all the answers gone?! there were at least 2 Commented Jun 6, 2013 at 18:07
  • None was correct. The posters deleted them by themself. Do you want a select or an update query? Commented Jun 6, 2013 at 18:07

2 Answers 2

2
update your_table t1
inner join
(
  select id, @rank := @rank + 1 as r
  from your_table, (select @rank := 0) r
  order by y
) t2 on t2.y = t.y
set z = r

SQLFiddle demo

Sign up to request clarification or add additional context in comments.

Comments

1

This is what I might call the "painful" solution. It uses a subquery to calculate the rank for each row:

update t
    set z = (select count(*) as cnt
             from (select t.* from t) t2
              where t2.y < t.y or t2.y = t.y and t2.x <= t.x
            )

Note that MySQL generates an error when you use the target table in a subquery in update and delete. There is a way around this. Just embed the table in a subquery.

You can also do this using a variable with a join:

update t join
       (select t.*, (@rank := @rank + 1) as seqnum
        from t cross join (select @rank := 0) const
        order by y
       ) t2
       on t.x = t2.x
set t.z = t2.seqnum;

The subquery calculates the sequence number with the order by. The outer update then assigns the value to the appropriate row. This assumes that x uniquely identifies each row.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.