Sql 了解Oracle别名-为什么除非在第二个查询中包装别名,否则在查询中无法识别别名?

Sql 了解Oracle别名-为什么除非在第二个查询中包装别名,否则在查询中无法识别别名?,sql,oracle,plsql,alias,Sql,Oracle,Plsql,Alias,我有一个问题 SELECT COUNT(*) AS "CNT", imei FROM devices 执行得很好。我想用WHERE语句进一步限制查询。合乎逻辑的下一步是修改查询,如下所示: SELECT COUNT(*) AS "CNT", imei FROM devices WHERE CNT > 1 但是,这会导致错误消息ORA-00904:CNT:无效标识符。出于某种原因,将查询包装到另一个查询中会产生所需的结果: SELECT * F

我有一个问题


SELECT COUNT(*) AS "CNT",
       imei
FROM   devices  
执行得很好。我想用WHERE语句进一步限制查询。合乎逻辑的下一步是修改查询,如下所示:


SELECT COUNT(*) AS "CNT",
       imei
FROM   devices
WHERE  CNT > 1 
但是,这会导致错误消息ORA-00904:CNT:无效标识符。出于某种原因,将查询包装到另一个查询中会产生所需的结果:


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

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

我可以想象,因为在处理WHERE子句并生成数据之前,别名不会分配给结果列。Oracle在这一行为上与其他DBMS不同吗?

因为Oracle说它不会:

指定列的别名 表示Oracle数据库将使用 此别名位于的列标题中 结果集。AS关键字是 可选择的有效地删除别名 重命名选定对象的“选择”列表项 查询的持续时间。别名可以 在order_by_子句中使用,但不能 查询中的其他子句


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

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

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

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

总而言之,这个小宝石说明:

造成混淆的一个常见原因很简单,就是SQL语法 元素的顺序与它们的执行方式不同。词汇 订购地址:

SELECT [ DISTINCT ]
FROM
WHERE
GROUP BY
HAVING
UNION
ORDER BY
为简单起见,并非所有SQL子句都列出。这是词汇顺序 从根本上不同于逻辑顺序,即不同于 执行:

FROM
WHERE
GROUP BY
HAVING
SELECT
DISTINCT
UNION
ORDER BY

因此,只有在执行了WHERE、HAVING和GROUP BY之后,使用As标记的任何内容才可用。

作为旁注:使用HAVING子句编写此带有聚合的查询更好:在OP的问题中,选择count*cnt,imei from devices GROUP BY imei HAVING count*>1,不仅仅是拥有会起到最好的作用,而是拥有才是答案。不能将where子句应用于count*之类的聚合,这就是HAVING子句存在的原因。此外,根据标准的SQL处理顺序,WHERE发生在SELECT之前,因此在应用WHERE子句时,别名CNT甚至不存在。From、Where、Group By、have、Select Order By