views:

89

answers:

2

I am cloning and extending the Google Tasks application. I want to be able to store the rows order. I have created a field in the database, named rowNumber. When the user inserts a row in the middle of others, I have to update this field in many other rows to achieve the desired output. There is a better way to do it?

BTW the application is made for the Google AppEngine (Python).

+1  A: 

One option might be to store rows as a linked list, where each row keeps an additional field for the next and previous row. The up side of this is that it requires touching only two other rows following an insert. the downside is that, (as I understand it) AppEngine doesn't have joins, so querying more than one row at a time will be pretty ugly.

TokenMacGuy
Querying it would be ugly even in SQL, right?
Jader Dias
And even if querying this is possible, it may not be very fast, am I right?
Martin Konicek
depends on your idea of ugly SQL. the sql query will just be a bunch of joins(equal to one less than the number of rows you wish to return), equating the next of one row to the pk of the subsequent row. speed depends on how well the DBMS optimizes that sort of query.
TokenMacGuy
+1  A: 

Make rowNumber a floating point number. When user inserts between rows x and y, the new row gets rowNumber = (x.rowNumber + y.rowNumer) / 2.

When you want to move a row, just update its rowNumber the same way based on target position.

New rows get rowNumber eg. MAX + 256.

Edit Microsoft solved this in SQL Server 2008 using new HierarchyId datatype. You can insert between 2 items almost as many times as you want - until you run out of HierarchyId max size.

Martin Konicek
Beautiful !
Jader Dias
I would not recommend using a float for this. It just makes it harder to predict the point at which you reach two values that are adjacent, that is a and b such that (a + b)/2 is equal either to a, or to b. You need to detect this situation and do something special. So you'd be just as well off starting with integers at intervals of 256 (or some larger number) as you are with floats, and it's easier with integers to space values out "evenly" across the full range of the type.
Steve Jessop
True, this situation can always happen, eg. after 50 insertions to same position (using high precision decimals as rowNumber). I ignored this. Using integers and recalculating whole table when you hit the limit would be better.
Martin Konicek