tags:

views:

31

answers:

2

I have a table I'd like to sort with a "priority" column. This column needs to be reordered when the priority of a record is changed or records are removed. Think of it as an array. The values will be modified in a UI so I want them to remain whole numbers and represent the true position within the larger recordset. The priority column won't have NULLs.

id       priority
1        2
2        1
3        4
4        3

Now say I change the priority of id 4 to 2 or I insert or delete a row how do I get all priorities to reshuffle so there are no gaps or duplicates and the highest possible priority is always the number of rows?

The table has a "date_modified" field which is accurate to the second and updated on insert/update so if needed it is possible to know which record was modified last (to break a tie when 2 records have the same priority)

A: 

Deleting a row:

UPDATE tbl SET priority = priority - 1 
WHERE priority > the_priority_of_what_you_deleted

Inserting a row (do this before the insert):

UPDATE tbl SET priority = priority + 1 
WHERE priority >= the_priority_about_to_be_inserted

You can put this kind of logic into INSERT and/or DELETE triggers, if you want.

egrunin
but these solutions won't help if I just change the priority of an existing row - there will be a gap. Also if I delete several rows at once or manually delete rows from pgadmin. I was hoping for something a bit more generic that could be run after a sequence of changes to "smooth" out the remaining values. The triggers might do the job but they make me nervous because I don't know how they will interact with my automated backup/restore system.
SpliFF
+1  A: 

Assuming you have 8.4 you can use window functions.

UPDATE test_priority 
SET priority = sub.new_priority
FROM (
    SELECT user_id, id, priority, rank() OVER (ORDER BY priority, date_modified) new_priority
    FROM test_priority
    WHERE user_id = $1
) sub 
WHERE test_priority.user_id = sub.user_id 
  AND test_priority.id = sub.id
  AND test_priority.priority <> sub.new_priority
Scott Bailey
that's more like it, I knew about rank() and I do have 8.4 but I couldn't make sense of how to use it in an UPDATE and gave up.
SpliFF
works a charm. it's times like this I wish you could add bounty to an answered question. i especially like that last little optimisation on the end... sure there's only 100 rows in this table and the updates are about once a day but hey, why update something if you don't have to?
SpliFF