54224
full outer join実行時はonとして指定したcolumnでデータがソートされると考えてよいのでしょうか？仕様で保証されているものでしょうか？

以下のスクリプトを実施したときの結果についてしりたいです。

＜スクリプト＞  
drop table if exists test1;  
drop table if exists test2;  
create temp table test1(num integer, val text);  
create temp table test2(num integer, val text);

insert into test1 values(1,'a');  
insert into test1 values(2,'b');  
insert into test1 values(3,'c');

insert into test2 values(1,'aa');  
insert into test2 values(5,'cc');  
insert into test2 values(3,'bb');

SELECT * FROM test1 FULL JOIN test2 ON test1.num = test2.num;

＜結果＞

```

    1   a   1   aa
    2   b       
    3   c   3   bb
            5   cc
    
```

上記のように、test2テーブルのnumがソートされた状態となります。

仕様の説明は以下のようになっています。  
<https://www.postgresql.jp/document/10/html/queries-table-expressions.html>

> FULL OUTER JOIN（完全外部結合）  
>  まず、内部結合が行われます。 その後、T2のどの行の結合条件も満たさないT1の各行については、T2の列をNULL値として結合行が追加されます。
> さらに、T1のどの行でも結合条件を満たさないT2の各行に対して、T1の列をNULL値として結合行が追加されます。

上記にはデータのオーダーに関する記載がありません。  
この意味を考えたときには以下のようにテーブルが作られてもおかしくはないのではないでしょうか？

```

    1   a   1   aa
    2   b       
            5   cc
    3   c   3   bb
    
```

また、試しに以下のようなスクリプトも実行してみました

＜スクリプト＞  
drop table if exists test1;  
drop table if exists test2;  
create temp table test1(num integer, val text);  
create temp table test2(num integer, val text);

insert into test1 values(1,'a');  
insert into test1 values(2,'b');  
insert into test1 values(6,'c');  
insert into test1 values(3,'c');

insert into test2 values(1,'aa');  
insert into test2 values(5,'cc');  
insert into test2 values(3,'bb');

SELECT * FROM test1 FULL JOIN test2 ON test1.num = test2.num;

＜結果＞

```

    1   a   1   aa
    2   b       
    3   c   3   bb
            5   cc
    6   c       
    
```

結果はやはりnum でソートされています。

full outer join実行時はonとして指定したcolumnでデータがソートされると考えてよいのでしょうか？仕様で保証されているものでしょうか？
CC BY-SA 4.0
2019-04-16T23:01:31.423
54222
2019-04-17T00:13:04.667
704
question
postgresql
postgresql full outer join の 順番について
**_full outer
join実行時はonとして指定したcolumnでデータがソートされると考えてよいのでしょうか？仕様で保証されているものでしょうか？_**

いいえ。

SQLのSELECT結果の順序については、この記述が全てを語っていると考えてください。

[7.5. Sorting Rows](https://www.postgresql.org/docs/9.5/queries-order.html)

> After a query has produced an output table (after the select list has  
>  been processed) it can optionally be sorted. If sorting is not chosen,  
>  the rows will be returned in an unspecified order. The actual order in  
>  that case will depend on the scan and join plan types and the order on  
>  disk, but it must not be relied on. A particular output ordering can  
>  only be guaranteed if the sort step is explicitly chosen.

[7.5. 行の並べ替え](https://www.postgresql.jp/document/9.5/html/queries-order.html)

>
> ある問い合わせが1つの出力テーブルを生成した後（選択リストの処理が完了した後）、並べ替えることができます。並べ替えが選ばれなかった場合、行は無規則な順序で返されます。そのような場合、実際の順序は、スキャンや結合計画の種類や、ディスク上に格納されている順序に依存します。
> しかし、当てにしてはいけません。明示的に並べ替え手続きを選択した場合にのみ、特定の出力順序は保証されます

もちろんFULL JOINの場合は例外だとか、FULL JOINのON句は並べ替えを指定しているものとするとかなんて言う記述はどこにも見つからないはずです。

(最初にヒットしたのがPostgreSQL 9.5用のページだったので、そのままそのリンクを使っていますが、どのバージョンでもほとんど同じ内容のはずです。)

* * *

あなたが試された条件では、PostgreSQLはON句に指定したカラムでソートされた順序で結果が出てくるようなアルゴリズムを採用しているのかもしれません。そんなアルゴリズムは採用しておらず、たまたまそう言う結果が出たのかもしれません。要は「当てにしてはいけません。」

条件をあちこち変えると違った結果が出るかもしれません、インデックスをかけてみるとか、両方のテーブルの要素数に極端に差があるとか。あれこれ変えても同様の結果が出るかもしれません。でも「当てにしてはいけません。」

あるいは近い将来のバージョンでもっと良いアルゴリズムが見つかったら、全然異なる結果が表示されるかもしれません。内部的にどんなアルゴリズムを採用するかについて、DBMS開発者が「前のバージョンと同じ順序で結果が出るようにする」、なんて「当てにしてはいけません。」

* * *

PostgreSQLに限らず、RDBMSのSELECT文では、明示的に順序を指定しない限り、結果の順序は保証されません。たまたま特定の条件下でいくつかやってみたらソートされている、と言うことがあってもそれはたまたまでしかありません。いくつかの例でそうは思えない結果が出たとしても、それはたまたまそうなったと思ってください。
CC BY-SA 4.0
2019-04-17T00:13:04.667
54224
2019-04-17T00:13:04.667
13972
54222
answer