web-dev-qa-db-ja.com

Postgresで和集合クエリのカスタムソート順を設定する方法

このようなクエリの場合(わかりやすくするために簡略化):

SELECT 'East' AS name, *
FROM events 
WHERE event_timestamp BETWEEN '2015-06-14 06:15:00' AND '2015-06-21 06:15:00' 

UNION

SELECT 'West' AS name, *
FROM events 
WHERE event_timestamp BETWEEN '2015-06-14 06:15:00' AND '2015-06-21 06:15:00'

UNION

SELECT 'Both' AS name, *
FROM events 
WHERE event_timestamp BETWEEN '2015-06-14 06:15:00' AND '2015-06-21 06:15:00'

結果の行の順序をカスタマイズしたいと思います。何かのようなもの:

ORDER BY name='East', name='West', name='Both'

または

ORDER BY 
    CASE
        WHEN name='East' THEN 1 
        WHEN name='West' THEN 2
        WHEN name='Both' THEN 3
        ELSE 4
    END;

ただし、Postgresは次のように文句を言います。

ERROR:  invalid UNION/INTERSECT/EXCEPT ORDER BY clause
DETAIL:  Only result column names can be used, not expressions or functions.
HINT:  Add the expression/function to every SELECT, or move the UNION into a FROM clause.

代替手段はありますか?

13
Dave

派生テーブルでラップします(これは "ヒント:....またはUNIONをFROM句に移動する"が示唆していることです)

select *
from (
  ... your union goes here ... 
) t
order by
    CASE
        WHEN name='East' THEN 1 
        WHEN name='West' THEN 2
        WHEN name='Both' THEN 3
        ELSE 4
    END;
24

目的の順序を示す列を追加してから、ORDER BYの順序列の位置を使用します。例:.

SELECT 1, 'East' AS name, *
...
UNION ALL
SELECT 2, 'West' AS name, *
...
ORDER BY 1

追加した列により、ユニオン内のすべてのセットがとにかく別個でなければならないため、おそらくUNION ALLも必要になることに注意してください。

14
Craig Ringer

ただし、順序付けのために列を追加することにより、UNION句がUNION ALLとまったく同じように機能するようになります(結果から重複する行が削除されるわけではありません)。

0
Pankus