views:

484

answers:

5

Hi all,

I have a table that contains tasks and I want to give these an explicit ordering based on the priority of the task. The only way I can think to do this is via an unique int column that indexes where the task is in term of the priority (i.e. 1 is top 1000 is low).

The problem is that say I wanted to update task and set its priority to a lower value , I would have to update all the other rows between its current value and its new value.

Can anyone suggest a better way of implementing this?

+3  A: 

Instead of creating an numbered column like you said, create a field called something like parent. Each row contains the pk of its parent item. When you want to move one item down just change its parent pk to the new one and the item(s) which reference it in their parent pk. Think singly linked lists.

Kevin
Sort of like a linked list I surpose?
Corin
I like this one :) The db will not protect your 'chain' of tasks though. If the app breaks a link the db will not care and you system will break. hehe. DBList :P
Arthur Thomas
that would be it. Unfortunately more complicated than a straight order, but it solves the problem of being able to move items without redoing the entire list.
Kevin
But how would you order that in a Select statement
Corin
Aurthur you're right about the db not protecting it. I should say that I am from the school that believes that people who modify the system should be able to program without a safety net so to speak.
Kevin
Colin on the ordering: off the top of my head you may not be able to. You might have to order it in code, but I'm not an sql expert so there could be a way of doing it, and it isn't coming to mind. I know a place to ask though :)
Kevin
oh I agree Kevin haha, but I like to think of ways to build my own nets when I see a problem. I would probably write a relinking procedure for this so applications did not do this task.
Arthur Thomas
This way does not enforce uniqueness. If task 3 already has task 2 as a parent, and you want to mark task 5 with task 2 as a parent, now task 2 has two children. You will be forced to put task three under task 5 first - but then you have to change task 6...
Doug L.
Hey arthur I didn't mean anything disrespectful about it. I guess I am a little bitter about being in discussions with programmers and their main response is that the system doesn't do everything for me, so I don't want to use that solution :)
Kevin
I saw no disrespect. I believe in responsibility :) I love db stuff though and like thinking of how to protect data and make sure it is meaningful.
Arthur Thomas
A: 

I would assign only a small number of values (1..10) and then ORDER BY Priority DESC, DateCreated ASC. If you need to have different priorities for each task you need to UPDATE WHERE Priority > xxx like you said.

Sklivvz
A: 

if no two tasks can have the same priority then I think that is what you have to do. But you could have a priority and a datemodified column and just sort by both to get the right order based on priority and last update if you allow priority to be duplicated.

James
+6  A: 

Use a real number value as the priority. You can always slide in a value between two existing values with something like newPri = task1Pri + (task2Pri - task1Pri)/2 where Task1 has the lower priority numeric value (which is probably the higher piority).

Corin points out that min and max priorities would have to be calculated for tasks inserted at the top or bottom of the priority list.

And joelhardi reminds us that a reorder process is a good idea to clean up the table from time to time.

Doug L.
That is an interesting idea. I'll have to remember that.
Kevin
Its a nice idea, though im not sure its very practical. As it would make inserts tricky as well. i.e. after you're first record does the next insert priority become MAX(realNumber)? If so what happens when you insert another value with a lower prioirty.
Corin
Thanks! (Now I feel bad - ha ha) I suppose you could still run out of values, although I have not stopped to figure out the limit. I'm actually kind of liking Skliwz's answer too.
Doug L.
Corin - I had not considered adding a task to the end of the list :)
Doug L.
On further thinking, I would make the last task something like Max(existing) + 1 (or 2, or 5). Not too high though.
Doug L.
This is what I do, unless I need auto_increment on new tasks, then I do kogus' solution and auto_increment ints by 100 or 1000 (and then write cronjob that checks for "small" gaps between items -- the result of *lots* of moving items around -- to indicate the need for a "reorder all" operation).
joelhardi
+1  A: 

I like Kevin's answer best, but if you want a quick-and-dirty solution, just do it the way you've already described, but instead of incrementing by 1, increment by 10 or 100... that way if you need to re-prioritize, you have some wiggle room between tasks.

JosephStyons