【问题标题】:PostgreSQL does not accept column alias in WHERE clausePostgreSQL 不接受 WHERE 子句中的列别名
【发布时间】:2026-02-19 20:05:02
【问题描述】:

pgexercisespgexercises关于join 3个不同的表,答案如下:

select mems.firstname || ' ' || mems.surname as member, 
    facs.name as facility, 
    case 
        when mems.memid = 0 then
            bks.slots*facs.guestcost
        else
            bks.slots*facs.membercost
    end as cost
        from
                cd.members mems                
                inner join cd.bookings bks
                        on mems.memid = bks.memid
                inner join cd.facilities facs
                        on bks.facid = facs.facid
        where
        bks.starttime >= '2012-09-14' and 
        bks.starttime < '2012-09-15' and (
            (mems.memid = 0 and bks.slots*facs.guestcost > 30) or
            (mems.memid != 0 and bks.slots*facs.membercost > 30)
        )
order by cost desc;

为什么我不能在WHERE 子句的SELECT 列表中引用cost 别名?
如果我运行相同的查询:

        ...
        where
        bks.starttime >= '2012-09-14' and 
        bks.starttime < '2012-09-15' and
        cost > 30
order by cost desc;

发生错误:

ERROR: column "cost" does not exist

this answer 我很清楚这是因为评估顺序。但是为什么允许order by cost desc;

【问题讨论】:

  • 起初我误解了你的问题:) 现在我完全同意上面的说法
  • 应用 where 语句时,在返回记录集之前不存在成本别名。在创建记录集之后应用 ORDER BY 语句意味着列别名随后可用。
  • 为了解决这个问题,我将SELECT ... c1 FROM t1 WHERE c1 ... 变成了SELECT ... FROM (SELECT ... c1 FROM t1) t2 WHERE t2.c1 ...。不确定这会如何影响性能。

标签: sql postgresql alias operator-precedence


【解决方案1】:

你问了两个问题:
1.

为什么我不能在 WHERE 子句中引用 SELECT 成本别名?

2.

但是为什么要按成本降序排序;允许吗?


manual has an answer for both of them here:

输出列的名称可用于引用该列的值 ORDER BYGROUP BY 子句,但不在 WHEREHAVING 中 条款;在那里你必须写出表达式。

它由SQL 标准 定义,原因是SELECT 查询中的事件顺序。在应用WHERE 子句时,尚未计算SELECT 列表中的输出列。但是对于ORDER BY,输出列是现成的。

因此,虽然起初这很不方便且令人困惑,但它仍然是有道理的。

相关:

【讨论】: