了解 Oracle 别名 - 为啥在查询中不识别别名,除非包装在第二个查询中?

Posted

技术标签:

【中文标题】了解 Oracle 别名 - 为啥在查询中不识别别名,除非包装在第二个查询中?【英文标题】:Understanding Oracle aliasing - why isn't an alias not recognized in a query unless wrapped in a second query?了解 Oracle 别名 - 为什么在查询中不识别别名,除非包装在第二个查询中? 【发布时间】:2011-05-27 14:37:34 【问题描述】:

我有一个问题


SELECT COUNT(*) AS "CNT",
       imei
FROM   devices  

执行得很好。我想使用 WHERE 语句进一步限制查询。 (人工)合乎逻辑的下一步是修改以下查询:


SELECT COUNT(*) AS "CNT",
       imei
FROM   devices
WHERE  CNT > 1 

但是,这会导致错误消息 ORA-00904: "CNT": invalid identifier。出于某种原因,将查询包装在另一个查询中会产生所需的结果:


SELECT *
FROM   (SELECT COUNT(*) AS "CNT",
               imei
        FROM   devices
        GROUP  BY imei)
WHERE  CNT > 1  

为什么 Oracle 在第二个查询中无法识别别名“CNT”?

【问题讨论】:

附带说明:这个查询(带有聚合)最好用 HAVING 子句编写:“select count(*) cnt, imei from devices group by imei having count(*) > 1”跨度> 【参考方案1】:

因为documentation 说它不会:

为列指定别名 表达。 Oracle 数据库将使用 列标题中的此别名 结果集。 AS 关键字是 选修的。别名有效 重命名选择列表项 查询的持续时间。别名可以 在 order_by_clause 中使用,但不是 查询中的其他子句。

但是,当您有一个内部选择时,这就像创建一个列别名生效的内联视图,因此您可以在外部级别使用它。

【讨论】:

【参考方案2】:

简单的答案是AS 子句定义了将在结果中调用的列,这是与查询本身不同的范围。

在您的示例中,使用 HAVING 子句效果最好:

SELECT COUNT(*) AS "CNT",
       imei
FROM   devices
GROUP  BY imei
HAVING COUNT(*) > 1

【讨论】:

在 OP 的问题中,不仅仅是 HAVING 效果最好,而是 HAVING 是答案。您不能将 where 子句应用于 count(*) 之类的聚合,这就是 HAVING 子句存在的原因。此外,根据标准 SQL 处理顺序,WHERE 发生在 SELECT 之前,因此别名 CNT 在应用 WHERE 子句的时间点甚至都不存在。来自、何处、分组依据、拥有、选择排序依据bennadel.com/blog/70-sql-query-order-of-operations.htm【参考方案3】:

总而言之,这个小宝石解释了:

10 Easy Steps to a Complete Understanding of SQL

一个常见的混淆来源是一个简单的事实,即 SQL 语法 元素没有按照它们执行的方式排序。词汇的 排序是:

SELECT [ DISTINCT ]
FROM
WHERE
GROUP BY
HAVING
UNION
ORDER BY

为简单起见,并未列出所有 SQL 子句。这个词序 从根本上不同于逻辑顺序,即从顺序 执行:

FROM
WHERE
GROUP BY
HAVING
SELECT
DISTINCT
UNION
ORDER BY

因此,您使用“AS”标记的任何内容只有在 WHEREHAVINGGROUP BY 已经执行后才可用。

【讨论】:

【参考方案4】:

我想是因为在 WHERE 子句被处理并生成数据之前,别名不会分配给结果列。 Oracle 在这种行为上与其他 DBMS 有何不同?

【讨论】:

以上是关于了解 Oracle 别名 - 为啥在查询中不识别别名,除非包装在第二个查询中?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决ORACLE中表一得列名的别名为另一表中的某一字段的值?

为啥 pi() 函数在使用其 JDBC 驱动程序的 Oracle 中不起作用?

Oracle从入门到精通 关于简单查询的问题

Oracle字段别名加as与不加的区别

为啥非贪心量词有时在 Oracle 正则表达式中不起作用?

为啥在超级终端中工作的永久别名在 vs-code bash 终端中不起作用?