28

With a query like this (simplified for clarity):

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'

I want to customise the order of the resulting rows. Something like:

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

Or

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

However, Postgres complains with:

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.

Do I have any alternative?

2 Answers 2

45

Wrap it in a derived table (which is what "HINT: .... or move the UNION into a FROM clause" is suggesting)

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;
Sign up to request clarification or add additional context in comments.

Comments

18

I'd add an extra column showing the desired ordering, then use ordinal column positions in the ORDER BY, e.g.

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

Note that you probably also want UNION ALL since your added columns ensure that every set in the union must be distinct anyway.

3 Comments

By adding an extra column for ordering purpose, however it makes the UNION clause to work exactly as a UNION ALL (it does not eliminate duplicate rows from the result).
How would you use this inside a function that must only return a single value?
@pir Wrap it in an outer query that SELECTs just the value-column, using FROM (SELECT ...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.