了解 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”标记的任何内容只有在 WHERE
、HAVING
和 GROUP BY
已经执行后才可用。
【讨论】:
【参考方案4】:我想是因为在 WHERE 子句被处理并生成数据之前,别名不会分配给结果列。 Oracle 在这种行为上与其他 DBMS 有何不同?
【讨论】:
以上是关于了解 Oracle 别名 - 为啥在查询中不识别别名,除非包装在第二个查询中?的主要内容,如果未能解决你的问题,请参考以下文章
如何解决ORACLE中表一得列名的别名为另一表中的某一字段的值?