| 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: | Whole Thread | Raw Message | 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
| 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. |