Re: Semantics around INSERT INTO with SELECT and ORDER BY.

From: Adrian Klaver <adrian(dot)klaver(at)aklaver(dot)com>
To: Steve Krenzel <sgk284(at)gmail(dot)com>, sravikrishna3(at)gmail(dot)com
Cc: pgsql-general(at)lists(dot)postgresql(dot)org
Subject: Re: Semantics around INSERT INTO with SELECT and ORDER BY.
Date: 2018-06-12 13:25:57
Message-ID: dfcb047d-78ff-2a61-42b5-97975dd0c693@aklaver.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On 06/12/2018 01:39 AM, Steve Krenzel wrote:
> This is relevant for tables that have a column with a SERIAL type, I
> need to guarantee that the relative ordering remains the same as the
> ordering of the selected result set.
>
> More concretely, given:
>
>     > CREATE TABLE foo (id SERIAL, val TEXT);
>     > CREATE TABLE bar (id SERIAL, val TEXT);
>     > INSERT INTO foo (val) VALUES ('A'), ('B'), ('C');
>     > TABLE foo;
>      id | val
>     ----+-----
>       1 | A
>       2 | B
>       3 | C
>     (3 rows)
>
> Then,
>
>     > INSERT INTO bar (val) SELECT val FROM foo ORDER BY id DESC;
>     > TABLE bar;
>      id | val
>     ----+-----
>       1 | C
>       2 | B
>       3 | A
>     (3 rows)
>
> The rows should be inserted in reverse. (Note: I don't care about the
> actual value of the id, only the relative ordering).
>
> Inserting more values should similarly append into the table in order
> (where "append" is used in terms of the serial id).
>
>     > INSERT INTO bar (val) SELECT val FROM foo ORDER BY id DESC;
>     > TABLE bar;
>      id | val
>     ----+-----
>       1 | C
>       2 | B
>       3 | A
>       4 | C
>       5 | B
>       6 | A
>     (6 rows)
>
> Or to put it another way, I want to select values from one table ordered
> by complex criteria and insert them into another table. I want to be
> able to retrieve the rows from the target table in the same order they
> were inserted, but I don't care about the specific ordering criteria. I
> only care about the order they were inserted.

That will only work until some other INSERT or UPDATE occurs. Using
table from your example:

UPDATE bar SET val = 'C1' where id = 1;

TABLE bar;
id | val
----+-----
2 | B
3 | A
4 | C
5 | B
6 | A
1 | C1
(6 rows)

You can use CLUSTER:

https://www.postgresql.org/docs/10/static/sql-cluster.html

to reestablish order based on an index, though that has the same issue:

"Clustering is a one-time operation: when the table is subsequently
updated, the changes are not clustered."

As has been pointed out order of rows is not guaranteed.

>
> On Tue, Jun 12, 2018 at 1:24 AM Ravi Krishna <sravikrishna3(at)gmail(dot)com
> <mailto:sravikrishna3(at)gmail(dot)com>> wrote:
>
> Why is it even important?  Once you use ORDER BY clause, you are
> guaranteed to get the rows in the order.  Why do you need how it was
> inserted in the first place.
>

--
Adrian Klaver
adrian(dot)klaver(at)aklaver(dot)com

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Tom Lane 2018-06-12 13:59:35 Re: Does pgAgent support chinese, japanese characters?
Previous Message David G. Johnston 2018-06-12 12:29:57 Re: Semantics around INSERT INTO with SELECT and ORDER BY.