1

I'm trying to update a column cohort_number in a table with sequential values from 1 to x (in this case 42) using a seq as below.

CREATE SEQUENCE seq start with 1 increment by 1 no maxvalue no cycle

UPDATE t1
SET cohort_number = next value for seq, instance_number = x.instanceNumber 
FROM 
( 
    SELECT id, 
    1 instanceNumber 
    FROM t1
) x 

DROP SEQUENCE seq

However on update rather than the first row cohort_number = 1, second row = 2 and so on, the first row cohort_column = 42, second row cohort_column = 2. I.e it appears that the update is being processed from the last entry in the select result rather than the first. Is there anyway around this?

I've also tried with ROW_NUMBER as below, but every value for the cohort_column is set to 1, which I believe is due to id having no duplicate values (but I'm guessing here)

UPDATE t1
SET cohort_number = x.cohort_number, instance_number = x.instance_number 
FROM 
( 
    SELECT id, 
    ROW_NUMBER() over (order by id) as cohort_number,
    1 instance_number 
    FROM t1
) x
3
  • Does that update statement executes correctly? It's trying to update T1 but it's in a subquery, should be out of scope. Commented Oct 30, 2019 at 12:30
  • Yeah, its probably where I've obfuscated the table name, variables etc incorrectly, before posting the question Commented Oct 30, 2019 at 12:38
  • Your second query is invalid since the alias t1 exists inside the derived table x and is not visible outside of x. Now would be a good time to post a simple script that demonstrates your problem that everyone can use as a common starting point. But perhaps this is no reason to actually store a value at all - sounds much more like a XY problem Commented Oct 30, 2019 at 12:58

2 Answers 2

2

The strange and proprietary UPDATE ... FROM syntax makes my head hurt.

This:

UPDATE t1
SET cohort_number = x.cohort_number, instance_number = x.instance_number 
FROM 
( 
    SELECT id, 
    ROW_NUMBER() over (order by id) as cohort_number,
    1 instance_number 
    FROM t1
) x

Doesn't work, because you're updating T1, without correlating it with x, and your're not updating x. Either would work.

I find it much easier to write a SELECT query that returns all the rows that will be updated, along with the new values for columns to be updated. Then update that:

with x as
(
    SELECT id, 
    cohort_number
    instance_number,
    ROW_NUMBER() over (order by id) as new_cohort_number,
    1 new_instance_number 
    FROM t1
)
update x set cohort_number = new_cohort_number, instance_number = new_instance_number
Sign up to request clarification or add additional context in comments.

1 Comment

Cheers, was banging my head against a brick wall here.
2

Why would you use a sequence for this? Just use row_number():

UPDATE toupdate
    SET cohort_number = seqnum,
        instance_number = new_instanceNumber 
    FROM (SELECT t1.*, ROW_NUMBER() OVER (ORDER BY id DESC) as seqnum
                 1 as new_instanceNumber 
          FROM t1
         ) toupdate;

3 Comments

I've tried with row_number but I seem to be doing something wrong... I'll update the question to show what I've tried.
@Dave0504 . . . I don't get why this would work, except for the typo (now fixed) around t.*.
It didn't, the accepted answer shows where I was going wrong.Cheers.

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.