在 WHERE 子句中使用列别名不起作用

Vic*_*tor 19 postgresql subquery alias where

给定一个users包含两个字段的表:idemail

select id, email as electronic_mail 
from (  
        select id, email 
        from users
) t 
where electronic_mail = ''
Run Code Online (Sandbox Code Playgroud)

Postgres 抱怨说:

ERROR:  column "electronic_mail" does not exist
Run Code Online (Sandbox Code Playgroud)

这个例子只是为了说明出现的问题。我的实际情况更复杂,我遍历 json 列中的元素数组,从每个元素中获取一个标量值。(如果有帮助,我可以分享一些代码。)

我真的不明白会有什么并发症,可能我不知道什么。我的印象是可以在WHERE子句中使用别名列而没有问题?

Erw*_*ter 28

手册在这里澄清:

输出列的名称可用于在ORDER BYandGROUP BY子句中引用列的值,但不能在WHEREorHAVING子句中引用 ;在那里你必须写出表达式。

这是根据 SQL 标准,可能不是很直观。这背后的(历史)原因是SELECT查询中的事件序列。WHEREHAVING得到解决之前被认为是列的别名,而GROUP BYORDER BY后来发生的,之后已应用于列别名。
还要注意输入和输出名称之间的冲突在不同的解决ORDER BYGROUP BY-另一个历史怪胎(与它背后的原因,但可能仍然混淆)。看:

最好避免先验地与输入列名称冲突的列别名。

旁白:您的示例中的子查询只是噪音,因为该WHERE子句是外部查询的一部分,因此该示例可以简化为:

select id, email as electronic_mail 
from users t 
where electronic_mail = '';  -- doesn't work
Run Code Online (Sandbox Code Playgroud)

  • 另一种解决方案是执行`SELECT id,electronic_mail FROM (SELECT id, email AS electronic_mail FROM users) AS t;`。小提琴可用 [此处](https://dbfiddle.uk/?rdbms=postgres_11&fiddle=29ae664b584a405c7fa11eadd5cd45de)。 (6认同)

小智 6

答案有点发布在评论中,但我遇到了类似的问题,并被引导到这里,我想我会分享作为答案。您的别名应该出现在内部选择中,而不是外部选择中。

select t.id, t.electronic_mail 
from (  
        select id, email as electronic_mail
        from users
) t 
where t.electronic_mail = '';
Run Code Online (Sandbox Code Playgroud)

对于现实世界的示例(即可以通过根本不包含别名来简化此示例):

select tb.lei, tb.lar_count 
from (
       select distinct(lei), count(*) as lar_count 
       from hmda_tb 
       where tract_id = 8029964900 
       group by lei
     ) as tb 
where tb.lar_count >= 10;
Run Code Online (Sandbox Code Playgroud)