Reputation: 2286
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
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
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;
Upvotes: 6
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
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