SQLite: How to update order data in table? - sql

I want to update a table to change the order of the data so it's ordered by some_column DESC.
I can do this by Selecting * and ordering by some_column DESC, and then inputting the data into a new table, but that's alot of hassle, so I'm wondering if there is another solution?
So what I want is to change this:
name|cost
John|50
Pete|75
Dojo|60
Neal|100
to
name|cost
Neal|100
Pete|75
Dojo|60
John|50
using the update statement. Is that possible?

You cannot rely on the way data is physically stored in the SQL table. The best you can do is create a VIEW on that table which is ordered the way you want it to be, and use that in your subsequent queries:
CREATE VIEW ordered_view AS
SELECT name, cost
FROM mytable
ORDER BY cost DESC;
SELECT name, cost FROM ordered_view;

Related

Use a specific column for ordering table

I have a table for categories on my posts database, I wanna make a specific order for them, so when I'm trying to insert a new record, It's not necessary to be stored at the end of table.
What is the best way to do that?
The order of rows and columns is immaterial to the DBMS. Rows are not stored at the end and select without order by does not guarantee the order of rows. Even if data can be stored ordered in the files, due to parallel execution, result is not ordered.
If you want to get ordered dataset, use ORDER BY in your query.
If you want ot order the extracted data then you should use the order by clause
SELECT Name, Order
FROM MyTalbe
WHERE ...
ORDER BY Order
Col1 being your column with the number from 1 to N

setting a sort order column quickly

Suppose I have a SQLite table People with columns recordId TEXT, name TEXT, job TEXT, sortOrder NUM.
I want to set the sortOrder column for all rows in the table based on sorting the table by name and then job.
I'm currently doing this by:
(1) SELECT recordId from People order by name, job
(1b) In the sqlite3_step() loop for that SELECT command, save the recordId values into a vector<string> orderedRecordIds. When we are done with this loop, orderedRecordIds has the recordId values in the desired order.
(2) In a loop, do a sqlite3_exec() for each recordId of the form
UPDATE People SET sortOrder = <i> WHERE recordId = '<orderedRecordIds[i]>'
That all works, but it's too slow.
For a database with 200k records, it takes about 1 second to do step (1), and 12 seconds to do step (2).
I'm not worried about the 1 second to do step (1).
But I'm trying to figure out how to make step (2) faster.
I do have an index on the recordId column, which I would think would help with finding each row to set the sortOrder value in step (2).
If I use rowid instead of recordId, it brings step (2) down to 10 seconds.
I was thinking it was all the separate calls to sqlite3_exec() that were slowing things down. So I tried doing it all in a single exec statement by building a huge CASE statement:
UPDATE People SET sortOrder = CASE
WHEN recordId='abc' THEN 0
WHEN recordId='def' THEN 1
/* <and so on for 200k rows> */
END
but that was extremely slow.
I feel like there should be a very fast way to do step (2). By comparison, when I use CREATE INDEX to create an index a column of this large table, it does it in like 20ms. I have this list of ordered record IDs, and just want to say "set the values of a numeric column according to that order."
Perhaps it's faster to create a temporary table with recordId and sortOrder columns, and then do the update based on a join with that table?
Or perhaps there is a way to do this all in a single step/loop instead of 2?
(By the way, I realize that as the problem is presented I could avoid the need for a sortOrder column by just creating an index on the name and job fields. But in my actual application some of the fields I'm sorting by are computed values, in some cases based on values from related tables. This is why I want to have a sortOrder column in the first place. Perhaps there is a way I can index based on related values in other tables. But for now please consider my question as stated.)
Why not use window functions, which are available in SQLite starting version 3.25 ?
If I followed you correctly, the following query gives you the result that you want:
select p.*, row_number() over(order by name, job) rn from people p;
You could just use this query to create a view rather than storing the value... When it comes to updating the table, it is a bit more complicated, because sqlite does not support joins in update statements. You could first materialize a temporary table that contains the sort orders, then use it to update your table, like:
create temp table people_tmp as
select recordId, row_number() over(order by name, job) rn from people;
update people
set sortOrder = (
select rn from people_tmp pt where pt.recordId = people.recordId
);

SQL Server date column sorting dates automatically

I have a table with a date column. I am inserting dates in that column using a DateTimePicker in C#.
Everything works fine. But I want the dates inserted in the table to be ordered. Currently when I add today's date in one row and then add yesterday's date or any past date, it gets added in the 2nd row ofc.
I want that to be added in 1st row instead. Before today's date, to make all the dates in order.
Is there any property of the date column I can use to ensure the dates order?
There is absolutely NO implicit order in SQL Server datatables! No index, no clustered index, no trick... A simple SELECT * FROM table may come back with sorted data - or not...
If you need your data sorted in a special way you must add an ORDER BY
Now one solution for your problem:
Create an updateable VIEW (https://msdn.microsoft.com/en-us/library/ms180800.aspx) on your table which is ordered like you want it. Than commuicate through this view...
Important is: Even when you specify SELECT TOP 100 PERCENT * FROM YourTable ORDER BY YourColumn the VIEW would not come back with sorted data...
The trick here is to introduce the sorting with a ROW_NUMBER()
I took for testing one of my tables. To make it more difficult I took one with an IDENTITY column.
And please keep in mind: The only sure order is the outermost ORDER BY
CREATE VIEW vwOneTableWithIdentityID
AS
SELECT ROW_NUMBER() OVER(ORDER BY SortColumn) AS OrderedInx
,* FROM OneTableWithIdentityID
GO
SELECT * FROM vwOneTableWithIdentityID;
GO
SET IDENTITY_INSERT OneTableWithIdentityID ON;
INSERT INTO vwOneTableWithIdentityID(OneTableWithIdentityIDID,AnotherID,SortColumn) VALUES(-5,1081,'aabc');
SET IDENTITY_INSERT OneTableWithIdentityID OFF;
GO
SELECT * FROM vwOneTableWithIdentityID
GO
DELETE FROM vwOneTableWithIdentityID WHERE OneTableWithIdentityIDID=-5;
GO
SELECT * FROM vwOneTableWithIdentityID;
GO
DROP VIEW vwOneTableWithIdentityID;
The physical order of a record is dependent on CLUSTER INDEX.
if you want DBMS order your data physically without
ORDER BY
clauses, create a clustered index on the field you want.

Trigger to order a table by date (SQL)

I would like to know how to order a table by date(the oldest date first) after the insert of a new value in the same table using a trigger.
Thank you
RDBMSs (or at least the common ones) have no notion of ordering a table - a table is just a bunch of rows, which the database may return in any arbitrary order.
Your way to control this order is to explicitly declare what order you want them with an order by clause in your query:
SELECT *
FROM my_table
ORDER BY last_modification_time

Insert into temp values (select.... order by id)

I'm using an Informix (Version 7.32) DB. On one operation I create a temp table with the ID of a regular table and a serial column (so I would have all the IDs from the regular table numbered continuously). But I want to insert the info from the regular table ordered by ID something like:
CREATE TEMP TABLE tempTable (id serial, folio int );
INSERT INTO tempTable(id,folio)
SELECT 0,folio FROM regularTable ORDER BY folio;
But this creates a syntax error (because of the ORDER BY)
Is there any way I can order the info then insert it to the tempTable?
UPDATE: The reason I want to do this is because the regular table has about 10,000 items and in a jsp file, it has to show every record, but it would take to long, so the real reason I want to do this is to paginate the output. This version of Informix doesn't have Limit nor Skip. I can't renumber the serial because is in a relationship, and this is the only solution we could get a fixed number of results on one page (for example 500 results per page). In the Regular table has skipped id's (called folio) because they have been deleted. if i were to put
SELECT * FROM regularTable WHERE folio BETWEEN X AND Y
I would get maybe 300 in one page, then 500 in the next page
You can do this by breaking up the SQL into two temp tables:
CREATE TEMP TABLE tempTable1 (
id serial,
folio int);
SELECT folio FROM regularTable ORDER BY folio
INTO TEMP tempTable2;
INSERT INTO tempTable1(id,folio) SELECT 0,folio FROM tempTable2;
In Informix when using a SELECT as a sub-clause in an INSERT statement, you are limited
to a subset of the SELECT syntax.
The following SELECT clauses are not supported in this case:
INTO TEMP
ORDER BY
UNION.
Additionally, the FROM clause of the SELECT can not reference the same table as referenced by the INSERT (not that this matters in your case).
It's been years since I worked on Informix, but perhaps something like this will work:
INSERT INTO tempTable(id,folio)
SELECT 0, folio
FROM (
SELECT folio FROM regularTable ORDER BY folio
);
You might try it iterating a cursor over the SELECT ... ORDER BY and doing the INSERTs within the loop.
It makes no sense to order the rows as you insert into a table. Relational databases do not allow you to specify the order of rows in a table.
Even if you could, SQL does not guarantee a query will return rows in any order, such as the order you inserted them. You must specify an ORDER BY clause to guarantee an order for a query result.
So it would do you no good to change the order in which you insert the rows.
As stated by Bill, there's not a lot of point ordering the input, you really need to order the output. In the simplistic example you've provided, it just makes no sense, so I can only assume that the real problem you're trying to solve is more complex - deduplication perhaps?
The functionality you're after is CREATE SEQUENCE, but I'm pretty sure it's not available in such an old version of Informix.
If you really need to do what you're asking, you could look into UNLOADing the data in the required order, and then LOADing it again. That would ensure the SERIAL values get allocated sequentially.
Would something like this work?
SELECT
folio
FROM
(
SELECT
ROWNUM n,
folio
FROM
regularTable
ORDER BY
folio
)
WHERE
n BETWEEN 501 AND 1000
It may not be terribly efficient if the table grows larger or you're fetching later "pages", but 10K rows is pretty small.
I don't recall if Informix has a ROWNUM concept, I use Oracle.