Postgres Case in Order by Using an Alias

How to use an ALIAS in a PostgreSQL ORDER BY clause?

You can always ORDER BY this way:

select 
title,
( stock_one + stock_two ) as global_stock
from product
order by 2, 1

or wrap it in another SELECT:

SELECT *
from
(
select
title,
( stock_one + stock_two ) as global_stock
from product
) x
order by (case when global_stock = 0 then 1 else 0 end) desc, title

Does a CASE statement lose alias scope in PostgreSQL?

What you are trying to do is not possible in Postgresql since it doesn't allow you to use an ALIAS within the same query as a field. Different from Mysql where you can do it.

To solve your problem you either create your query as a subquery and then your alias will be a field therefore can be used as:

select useid, lobjectid from (
select
case
when sa.luserid > 0 then sa.luserid
when sa.lgroupid > 0 then sa.lgroupid
when sa.lldapid > 0 then sa.lldapid
end as useid,
lobjectid
from security s
left join users u on s.luserid = u.id
left join usergroups g on s.lgroupid = g.id
) as t
order by
case
when 'user selection' = 'all objects by user' then useid
else lobjectid
end

Or you can repeat the entiry case block

  select
case
when sa.luserid > 0 then sa.luserid
when sa.lgroupid > 0 then sa.lgroupid
when sa.lldapid > 0 then sa.lldapid
end as useid,
lobjectid
from security s
left join users u on s.luserid = u.id
left join usergroups g on s.lgroupid = g.id
order by
case
when 'user selection' = 'all objects by user' then
case
when sa.luserid > 0 then sa.luserid
when sa.lgroupid > 0 then sa.lgroupid
when sa.lldapid > 0 then sa.lldapid
end
else lobjectid
end

Some engines will let you use the order number of the field on the select scope to the order by like:

select a, b, c from sometable order by 1, 2

Which means that this query will be ordered by the fields a and b

Postgres CASE in ORDER BY using an alias

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;

Can i use 'alias' AS in CASE Statement PostgreSQL

You could use a CTE

WITH CTE as (
SELECT
id
, quantity
, unit_price,
(antity * unit_price) as price
FROM OrderDetails
)
SELECT
id
, quantity
, unit_price
, price
CASE
WHEN price > 5000 THEN price * 0.2
WHEN price > 3000 THEN price * 0.15
ELSE null
END

AS discount

FROM OrderDetails;

How to use order by case with an alias column on Postgresql?

Wrap it in a derived table:

select *
from (
SELECT my_column AS alias_column
FROM my_table
) t
ORDER BY CASE alias_column
WHEN 1 THEN 1
WHEN 2 THEN 2
END ASC

PostgreSQL: case when using alias column

You can use WITH clause:

with a as (select count(*) score from t)
select case when score > 5 then score else 0 end from a;

Or subquery (inline-view):

select case when score > 5 then score else 0 end 
from (select count(*) score from t) t;

ORDER BY Alias not working

You can use ORDER BY 1 to order by the first field, which is "Fruits". The same is valid for GROUP BY

Update

For the order, instead of doing the case in the order by, create a new column in.. say.. the second position:

(CASE 
WHEN "Fruits" = 'Apple' THEN 1
WHEN "Fruits" = 'Pear' THEN 2
WHEN "Fruits" = 'Grapes' THEN 3
ELSE 4 ) as Order

Then in you ORDER BY 2.

Why can't i refer to a column alias in the ORDER BY using CASE?

This has to do with how a SQL dbms resolves ambiguous names.

I haven't yet tracked down this behavior in the SQL standards, but it seems to be consistent across platforms. Here's what's happening.

create table test (
col_1 integer,
col_2 integer
);

insert into test (col_1, col_2) values
(1, 3),
(2, 2),
(3, 1);

Alias "col_1" as "col_2", and use the alias in the ORDER BY clause. The dbms resolves "col_2" in the ORDER BY as an alias for "col_1", and sorts by the values in "test"."col_1".

select col_1 as col_2
from test
order by col_2;

col_2
--
1
2
3

Again, alias "col_1" as "col_2", but use an expression in the ORDER BY clause. The dbms resolves "col_2" not as an alias for "col_1", but as the column "test"."col_2". It sorts by the values in "test"."col_2".

select col_1 as col_2
from test
order by (col_2 || '');

col_2
--
3
2
1

So in your case, your query fails because the dbms wants to resolve "NewValue" in the expression as a column name in a base table. But it's not; it's a column alias.

PostgreSQL

This behavior is documented in PostgreSQL in the section Sorting Rows. Their stated rationale is to reduce ambiguity.

Note that an output column name has to stand alone, that is, it cannot be used in an expression — for example, this is not correct:

SELECT a + b AS sum, c FROM table1 ORDER BY sum + c;          -- wrong

This restriction is made to reduce ambiguity. There is still ambiguity if an ORDER BY item is a simple name that could match either an output column name or a column from the table expression. The output column is used in such cases. This would only cause confusion if you use AS to rename an output column to match some other table column's name.

Documentation error in SQL Server 2008

A slightly different issue with respect to aliases in the ORDER BY clause.

If column names are aliased in the SELECT list, only the alias name can be used in the ORDER BY clause.

Unless I'm insufficiently caffeinated, that's not true at all. This statement sorts by "test"."col_1" in both SQL Server 2008 and SQL Server 2012.

select col_1 as col_2
from test
order by col_1;

PostgreSQL : Cannot use column alias in CASE statement

It is problematic to use the alias "balance" inside of a CASE statement because you try to use alias as a field within the same query and Postgresql restricts it.

You can try to write a subquery.
As DB schema wasn't provided, I couldn't test this query:

WITH t AS (
SELECT
((SELECT SUM(amount) FROM trans WHERE u.mail = paid_to)-
(SELECT SUM(amount) FROM trans WHERE u.mail = paid_by)) AS balance,
u.credit_limit
FROM user u
LEFT JOIN trans t ON u.mail = t.paid_to OR u.mail = t.paid_by
)
SELECT t.balance,
CASE WHEN t.balance < t.credit_limit THEN 'YES' ELSE 'NO' END AS result
FROM t;

Using calculation with an an aliased column in ORDER BY

The documentation clearly states that:

The column names referenced in the ORDER BY clause must correspond to
either a column or column alias in the select list or to a column
defined in a table specified in the FROM clause without any
ambiguities. If the ORDER BY clause references a column alias from
the select list, the column alias must be used standalone, and not as
a part of some expression
in ORDER BY clause:

Technically speaking, your query should work since order by clause is logically evaluated after select clause and it should have access to all expressions declared in select clause. But without looking at having access to the SQL specs I cannot comment whether it is a limitation of SQL Server or the other RDBMS implementing it as a bonus feature.

Anyway, you can use CROSS APPLY as a trick.... it is part of FROM clause so the expressions should be available in all subsequent clauses:

SELECT item
FROM t
CROSS APPLY (SELECT item + '') AS CA(item_for_sort)
ORDER BY item_for_sort


Related Topics



Leave a reply



Submit