Best practice for handling positions of rows - mysql

What is the best practice for moving rows. So that you might want to change order of items. Now if you make a new column called order_id or something, wouldn't that fail if I delete or select rows.
Another method I guess is to just switch values completely with an primary ID, so just values except the ID are changed. however I do not know what people usually use. There are so many websites that give you the ability to change order of things.how so they do that?

Every SQL statement that returns a visible result set should include an ORDER BY clause so that the results are consistent. The Standard does not guarantee that the order of rows in a particular table will remain constant or consistent, even if obvious changes aren't made to the table.
What you use for your ORDER BY clause depends on the use case. A date value is the usual choice for a comment thread or blog entry ordering. However, if you want the user to be able to customize the order that a result set shows in, then you have to provide a column that represents the position of the row, and adjust the value of that column when the user makes changes to the order they see.
For example, if you decide that the column will contain a sequential number, starting with 1 for the first row, 2 for the second, etc. then you will be ok to delete rows when they need to be deleted without having to do updates. However, if you insert a row, you will need to give the row you insert the sequential number appropriate for it's position, and update all rows below that with their new position. Same goes for if you move a row from somewhere else to a new location; the rows between the new and old locations need to be updated with new postion indexes.

Related

Mysql inserts in the middle instead at the end of table

I am new to database. I deleted few rows (till end of table) from a database table. Now every time i execute INSERT query via php, it inserts new row immediately after last deleted row and pushes the previous inserts down by one row.
As shown in above figure, the rows are deleted from 2019-08-18 (red rectangle) via the query:
DELETE FROM mytable WHERE date > '2019-08-18'
Now new inserts have wrong order as shown in green rectangle in above figure. Though the row with date 2019-08-19 is inserted first, it is pushed to the end of table.
What am i doing wrong?
Most relational databases will not return the rows in any particular order unless you ask explicitly. They'll just do whatever's easiest. Often that's insertion order, or maybe order on disk, or whatever index was last used. It's really arbitrary and may even change from version to version of the same database platform.
"If you cared you'd ask" is the principle at work here. You didn't ask, so MySQL presumes you don't care.
Add an ORDER BY clause to get predictable orders. Otherwise be prepared for the unexpected.

How to implement a MySQL table that the row order can be customized? [duplicate]

This question already has answers here:
Making changes to multiple records based on change of single record with SQL
(3 answers)
Closed 5 years ago.
I'd like to save some data in a MySQL table. The data have their orders which can be modified at my will. Say I have 10 rows. I want to move the 10th row to the 5th position, or insert some more rows between 2nd and 3rd position. Then, with a viewer I can get the data with the order I set. How can I implement such a table?
As I thought, I would save the order as float number in a new column. Each time I change the order, say, move 10th row between 5th and 6th, I would get the order number of 5th and 6th and get the average number of them, and update the order column of 10th row. Then I can get the data that ORDER BY order column. But I don't think it's a good idea. Any help about this problem?
You don't order the table, that makes no sense. You are actually not interested in the order the entries are placed in that table. Consider it random.
You are interested in the order you want to see the entries in. For that you create an additional column, call it "select_order" or "priority", however you like. In that you store simple integers which you use to describe the order you want to see the entries in.
Now you can "re-order" the entries however you like by changing those numbers in that order column. At query time you add an ORDER BY select_order clause to your SELECT query and will receive the entries in exactly the order you want.
This is the standard approach for relational database models. Which does not mean that there are no other approaches that might be interesting to look into for very special situations:
a priority table instead of a column which is joined during the SELECT query. This might make sense for situations with much more write than read operations. Note the much however.
a multiple column approach for situations where you can group entries and only re-order inside such groups. That dramatically reduces the number of entries you have to updated in case or re-ordering.

tracking actual changes in rows when updating table

I have a table which i keep on updating, from the values of other source in my code. The value I update may or may not be same as the value already in the row.
I need some kind of algorithm may be via mysql (db) or otherwise (part of code) so that I later may be able to identify which rows have a changed value.
There is a date modified column which I change. But that will not be a true indicator as it will always be updated. I want a way by which I can determine whether some predefined columns have changed values,
One solution is this: I can do a select query, then compare and update a changed flag in the table. But that seems complex and not for me as I have a table with a lot of records
Another solution might be to save the md5 checksum of the values in a column and while updating compare the previous md5 and current md5 and so on.
I want to know the best solution.
There's a fairly simple way to handle this problem. Let's think of it as managing when a row's timestamp gets updated.
First of all, as I'm sure you know, your table needs a timestamp column with default settings for INSERT and UPDATE. That looks like this if the column is called ts.
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Second, you can use an UPDATE query like this to change the values in a row.
UPDATE stock
SET val1 = 'newval1',
val2 = 'newval2',
changed_by = 'current_user_id'
WHERE id = 'id_to_change'
AND NOT (val1 == 'newval1' AND val2 == 'newval2')
The AND NOT clause on the WHERE will prevent the update from taking place unless 'newval1' or 'newval2' would actually provide new values. This works because no rows match the WHERE clause in the update.
When the update is prevented from taking place your automatically set ts column will not change. Neither will the changed_by column be set to the present user's user_id. So, you have the time and user of the most recent genuine change.
Also, many host language interfaces to MySQL have a method call to determine how many rows were affected by a recent UPDATE operation. With this technique, you'll get back zero rows when the row is not updated. That might be convenient for your user interface.
Also, this technique uses a single query, so it's safe if more than one user is trying to update the same row at the same time. There's no need to use a transaction to guarantee that.
(Note that tracking the changed_by user is optional, and will only work if your application can provide the current user's actual id.)
This is reasonably efficient as long as the database search for WHERE id = 'id_to_change' works quickly.
It does require reworking your application's UPDATE queries. But so would any other approach to this problem.

order and change one column of database

I have one col in my database named position used for ordering. However, when some records is deleted, the sequence get messed up. I want to reorder this col when the table is changed(maybe use trigger).
position(old) -> position(new)
1 1
3 2
7 3
8 4
like this.
I think there will not exist equal number even in position(old), because I have already attach some function in PHP to reorder the column when updates occurs. However, when a record is deleted because of the deletion of its parent, function will not be called.
Thanks for help!
If you are using the column just for ordering, you do not need to update column on deletion, because the order will still be correct. And you will save some resources.
But if you really need to update by sequence, look at this answer:
updating columns with a sequence number mysql
I believe (as scrowler wrote) the better way in such case is to update rows from the application, after application deletes the parent record.
If you decide to update it in the application then...
If position = n is deleted, you logic should be set position = position - 1 where position > n
Please note that this will work only if you delete one record at a time from your application and before assuming that before the delete is triggered the data is already in sequence

Create ordering in a MySQL table without using a number (because then it's hard to put something in between)

I have a long list of items (say, a few million items) in a mysql table, let's call it mytable and it has the field mytable.itemid.
The items are given an order, and can be re=ordered by the user by drag and drop. If I add a field called mytable.order and just put numbers in them, it creates problems: what if I want to move an item between 2 other items? Then all the order fields have to be updated? That seems like a nightmare.
Is there a (scalable) way to add order to a table that is different from just giving every item a number, order by that, and do loads of SQL queries everytime the order is changed?
You can either create a trigger or stored procedure to resequence the order values appropriately, or drop all the associated records and insert new ones in the new order.
You can use fractions (two integers, i.e. a/b). Always there is at least one rational between two other.