可以在同一个select语句中使用计算或重命名的列(不使用子查询)

时间:2014-10-15 06:48:24

标签: sql arrays postgresql-9.1

可以使以下声明起作用吗?:

SELECT
id AS "ID",
unnest(agent_ids) AS "AgentID",
idtotitle('users', "AgentID") AS "AgentName", -- lookup agent name
from users;
  

错误:列“AgentID”不存在第4行:idtotitle('users',   “AgentID”)AS“AgentName”

似乎告诉我无法在同一语句中引用unnested列值。我可以将整个事物包装在一个子选择中,但由于该语句是由不支持子选择语法的现有代码生成的,所以我希望尽可能避免这种情况。

我也很好奇为什么上面的内容不起作用。

编辑:不是特定于unexst(),这也失败了:

SELECT
id AS "UserID",
'User ' || "UserID" AS "UserName" 
FROM users;
  

错误:列“UserID”不存在

所以你不能在同一个语句中访问你创建/重命名的列?

2 个答案:

答案 0 :(得分:3)

您已经知道解决方案 - 使用子查询,CTE或重复表达式。

原因很简单。 SQL标准未指定select子句中表达式的评估顺序。您可能认为从左到右按照书面处理它们是合乎逻辑的,但定义SQL的权力从未强制要求。

因此,可以在定义列别名的表达式之前评估使用列别名的表达式 - 从而导致问题。为了防止这种情况,SQL引擎不允许您在定义的同一级别使用列别名。

答案 1 :(得分:1)

有趣的是,您无法重用在同一SELECT子句中SELECT子句中声明的列别名。从技术上讲,没有理由缺少此功能。数据库可以检测引用依赖图并检查周期,并允许非循环引用,但这在大多数数据库中根本不可能(有些数据库允许某些“相同范围列引用”,特别是在窗口函数时参与其中)。

以下是PostgreSQL中可能的概述:

无法引用在同一SELECT范围内声明的列别名:

select 1 as "ID", "ID" + 1;       -- This would be very useful but isn't possible
select 1 as "ID" where "ID" = 1;  -- This would be very useful but isn't possible
select 1 as "ID" having "ID" = 1; -- This doesn't even make sense

可以引用在同一SELECT范围内声明的列别名:

select 1 as "ID" group by "ID";   -- Only few databases allow this
select 1 as "ID" order by "ID";   -- This is explicitly allowed by the SQL standard

因此,正如其他人所提到的,就您的问题而言,您将不得不求助于在表格中生成计算出的值,例如:公用表表达式或派生表。