I have the following query which works great in Postgres 9.1:
SELECT users.id, GREATEST(
COALESCE(MAX(messages.created_at), '2012-07-25 16:05:41.870117'),
COALESCE(MAX(phone_calls.created_at), '2012-07-25 16:05:41.870117')
) AS latest_interaction
FROM users LEFT JOIN messages ON users.id = messages.user_id
LEFT JOIN phone_calls ON users.id = phone_calls.user_id
GROUP BY users.id
ORDER BY latest_interaction DESC
LIMIT 5;
But what I want to do is something like this:
SELECT users.id, GREATEST(
COALESCE(MAX(messages.created_at), '2012-07-25 16:05:41.870117'),
COALESCE(MAX(phone_calls.created_at), '2012-07-25 16:05:41.870117')
) AS latest_interaction
FROM users LEFT JOIN messages ON users.id = messages.user_id
LEFT JOIN phone_calls ON users.id = phone_calls.user_id
GROUP BY users.id
ORDER BY
CASE WHEN(
latest_interaction > '2012-09-05 16:05:41.870117')
THEN 0
WHEN(latest_interaction > '2012-09-04 16:05:41.870117')
THEN 2
WHEN(latest_interaction > '2012-09-04 16:05:41.870117')
THEN 3
ELSE 4
END
LIMIT 5;
And I get the following error: ERROR: column "latest_interaction" does not exist
It seems like I cannot use the alias for the aggregate latest_interaction in the order by clause with a CASE statement.
Are there any workarounds for this?
Due to logical query processing order, alias can be used in order by.
You can use an alias for any field or aggregated field in a SELECT statement in a SOQL query. Use a field alias to identify the field when you're processing the query results in your code. Specify the alias directly after the associated field.
ASC order is the default. Ascending order puts smaller values first, where “smaller” is defined in terms of the < operator. Similarly, descending order is determined with the > operator.
Try to wrap it as a subquery:
SELECT *
FROM
(
SELECT users.id,
GREATEST(
COALESCE(MAX(messages.created_at), '2012-07-25 16:05:41.870117'),
COALESCE(MAX(phone_calls.created_at), '2012-07-25 16:05:41.870117')
) AS latest_interaction
FROM users LEFT JOIN messages ON users.id = messages.user_id
LEFT JOIN phone_calls ON users.id = phone_calls.user_id
GROUP BY users.id
) Sub
ORDER BY
CASE WHEN(
latest_interaction > '2012-09-05 16:05:41.870117')
THEN 0
WHEN(latest_interaction > '2012-09-04 16:05:41.870117')
THEN 2
WHEN(latest_interaction > '2012-09-04 16:05:41.870117')
THEN 3
ELSE 4
END
LIMIT 5;
The PG manual says the ORDER BY expression:
Each expression can be the name or ordinal number of an output column (SELECT list item), or it can be an arbitrary expression formed from input-column values.
The sub-query solution from @Mahmoud will work, or you can create the ORDER BY using the original columns messages.created_at or phone_calls.created_at
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With