Oracle SQL Plus WITH子句"无效标识符"

时间:2015-10-07 03:50:03

标签: sql oracle

使用SQL * Plus 11.2在Oracle Database 11g上运行数据库。是否在WITH子句中不允许使用聚合方法,还是WITH做了一些神奇的事情?这段代码告诉我" most_expensive"是无效的标识符。然而,子查询没有问题。

WITH most_expensive AS (SELECT MAX (enrollment_cost) FROM Enrollments)
SELECT e.member_id
FROM Enrollments e
WHERE e.enrollment_cost = most_expensive;

3 个答案:

答案 0 :(得分:3)

查询因子(带子句)允许您定义临时表别名。 在您的示例中,most_expensive将引用包含具有单个列的单个行的表对象。您可以在查询中的任何位置使用它,您可以在其中使用表。 现在,如果你创建一个名为t1的表(使用create table statment),给它一列并插入1行,你仍然无法做到" WHERE x = t1"。
换句话说,子查询并不总是与表相同,而WITH子句为您提供的行为类似于表,而不是像子查询。

以下作品:

WITH most_expensive AS (SELECT MAX (enrollment_cost) FROM Enrollments)
SELECT member_id
FROM Enrollments e
WHERE e.enrollment_cost = (select * from most_expensive);

http://sqlfiddle.com/#!4/9eecb7/6340

答案 1 :(得分:1)

我认为在这里使用子查询因子分析(WITH子句)没有任何好处。查询可以简单地写成:

SELECT member_id
FROM Enrollments e
WHERE e.enrollment_cost =
  (SELECT MAX (enrollment_cost) FROM Enrollments
  );

比较解释计划:

没有子查询保理:

SQL> set autot on explain
SQL> SELECT empno FROM emp e WHERE e.sal =
  2    (SELECT MAX (sal) FROM emp
  3    );

     EMPNO
----------
      7839


Execution Plan
----------------------------------------------------------
Plan hash value: 1876299339

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     1 |     8 |     8   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL  | EMP  |     1 |     8 |     4   (0)| 00:00:01 |
|   2 |   SORT AGGREGATE    |      |     1 |     4 |            |          |
|   3 |    TABLE ACCESS FULL| EMP  |    14 |    56 |     4   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("E"."SAL"= (SELECT MAX("SAL") FROM "EMP" "EMP"))

使用子查询保理:

SQL> WITH max_sal AS
  2    ( SELECT MAX (sal) sal FROM emp
  3    )
  4  SELECT empno FROM emp e WHERE e.sal =
  5    (SELECT sal FROM max_sal
  6    );

     EMPNO
----------
      7839


Execution Plan
----------------------------------------------------------
Plan hash value: 73843676

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     1 |     8 |     8   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL   | EMP  |     1 |     8 |     4   (0)| 00:00:01 |
|   2 |   VIEW               |      |     1 |    13 |     4   (0)| 00:00:01 |
|   3 |    SORT AGGREGATE    |      |     1 |     4 |            |          |
|   4 |     TABLE ACCESS FULL| EMP  |    14 |    56 |     4   (0)| 00:00:01 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("E"."SAL"= (SELECT "SAL" FROM  (SELECT MAX("SAL") "SAL"
              FROM "EMP" "EMP") "MAX_SAL"))

请参阅应用的过滤器,您所做的只是使其嵌套查询并深入一级而不实际添加任何好处。

答案 2 :(得分:0)

您的因子查询(表)名为most_expensive,但您将其用作列名。在这种情况下,您应该使用keep first

SELECT max(member_id) KEEP (DENSE_RANK FIRST ORDER BY enrollment_cost desc nulls last) "Best"
FROM Enrollments e
WHERE e.enrollment_cost = most_expensive;