了解Oracle别名 - 除非在第二个查询中包含,否则为什么查询中不能识别别名?

sim*_*mon 7 sql oracle alias plsql

我有一个问题


SELECT COUNT(*) AS "CNT",
       imei
FROM   devices  
Run Code Online (Sandbox Code Playgroud)

执行得很好.我想用WHERE语句进一步限制查询.(人性)逻辑下一步是随后修改查询:


SELECT COUNT(*) AS "CNT",
       imei
FROM   devices
WHERE  CNT > 1 
Run Code Online (Sandbox Code Playgroud)

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


SELECT *
FROM   (SELECT COUNT(*) AS "CNT",
               imei
        FROM   devices
        GROUP  BY imei)
WHERE  CNT > 1  
Run Code Online (Sandbox Code Playgroud)

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

Cra*_*aig 13

因为文档说它不会:

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

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


Dat*_*jam 8

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

在您的示例中,使用该HAVING子句最有效:

SELECT COUNT(*) AS "CNT",
       imei
FROM   devices
GROUP  BY imei
HAVING COUNT(*) > 1
Run Code Online (Sandbox Code Playgroud)

  • 在 OP 的问题中,不仅仅是 HAVING 效果最好,而且 HAVING 才是答案。您不能将 where 子句应用于像 count(*) 这样的聚合,这就是存在 HAVING 子句的原因。此外,根据标准 SQL 处理顺序,WHERE 发生在 SELECT 之前,因此在应用 WHERE 子句时,别名 CNT 甚至不存在。从,哪里,分组依据,拥有,选择排序依据 http://www.bennadel.com/blog/70-sql-query-order-of-operations.htm (2认同)

Dav*_*fer 5

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

完全理解 SQL 的 10 个简单步骤

造成混淆的一个常见原因是一个简单的事实:SQL 语法元素的顺序并不按照它们的执行方式排序。词汇顺序是:

SELECT [ DISTINCT ]
FROM
WHERE
GROUP BY
HAVING
UNION
ORDER BY
Run Code Online (Sandbox Code Playgroud)

为简单起见,未列出所有 SQL 子句。这种词法顺序与逻辑顺序(即执行顺序)有根本的不同:

FROM
WHERE
GROUP BY
HAVING
SELECT
DISTINCT
UNION
ORDER BY
Run Code Online (Sandbox Code Playgroud)

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