lgersman
lgersman

Reputation: 2286

how to normalize / update a "order" column

i have a table "mydata" with some data data :

id    name       position
===========================
4     foo        -3 
6     bar        -2 
1     baz        -1
3     knork      -1
5     lift       0
2     pitcher    0

i fetch the table ordered using order by position ASC;

the position column value may be non unique (for some reason not described here :-) and is used to provide a custom order during SELECT.

what i want to do :

i want to normalize the table column "position" by associating a unique position to each row which doesnt destroy the order. furthermore the highest position after normalising should be -1.

wished resulting table contents :

id    name       position
===========================
4     foo        -6 
6     bar        -5 
1     baz        -4
3     knork      -3
5     lift       -2
2     pitcher    -1

i tried several ways but failed to implement the correct update statement.

i guess that using

generate_series( -(select count(*) from mydata), -1) 

is a good starting point to get the new values for the position column but i have no clue how to merge that generated column data into the update statement.

hope somebody can help me out :-)

Upvotes: 3

Views: 463

Answers (4)

lgersman
lgersman

Reputation: 2286

@a_horse_with_no_name is really near the truth - thank you !

UPDATE temp 
  SET position=t.rn 
  FROM (SELECT 
            id, name, 
            -((select count( *) 
          FROM temp)
            +1-row_number() OVER (ORDER BY position ASC)) as rn
        FROM temp) t 
  WHERE temp.id=t.id;

SELECT * FROM temp ORDER BY position ASC;

see http://sqlfiddle.com/#!1/d1770/6

Upvotes: 1

user330315
user330315

Reputation:

Something like:

with renumber as (
  select id,
         -1 * row_number() over (order by position desc, id) as rn
  from foo
)
update foo
  set position = r.rn
from renumber r
where foo.id = r.id
  and position <> r.rn;

SQLFiddle Demo

Upvotes: 6

Devart
Devart

Reputation: 121922

Try this one -

Query:

CREATE TABLE temp
(
      id INT
    , name VARCHAR(10)
    , position INT
)

INSERT INTO temp (id, name, position)
VALUES 
    (4, 'foo', -3),
    (6, 'bar', -2),
    (1, 'baz', -1),
    (3, 'knork', -1),
    (5, 'lift', 0),
    (2, 'pitcher', 0)

SELECT 
      id
    , name
    , position = -ROW_NUMBER() OVER (ORDER BY position DESC, id) 
FROM temp
ORDER BY position

Update:

UPDATE temp
SET position = t.rn
FROM (
    SELECT id, rn = - ROW_NUMBER() OVER (ORDER BY position DESC, id) 
    FROM temp
) t
WHERE temp.id = t.id

Output:

id          name       position
----------- ---------- --------------------
4           foo        -6
6           bar        -5
3           knork      -4
1           baz        -3
5           lift       -2
2           pitcher    -1

Upvotes: 2

chetan
chetan

Reputation: 2886

update mydata temp1, (select a.*,@var:=@var-1 sno from mydata a, (select @var:=0) b 
order by position desc, id asc) temp2
set temp1.position = temp2.sno
where temp1.id = temp2.id;

Upvotes: 0

Related Questions