3

我知道 Oracle RDMS 无法合并其中包含集合运算符的视图。我想知道为什么会这样。

例如,这个:

SELECT u.*
FROM
 (
  SELECT a.a1    A,
        a.a2    B
   FROM tab_a a
UNION ALL
  SELECT b.b1    A,
         b.b2    B
    FROM tab_b b
)     u,
tab_p p
WHERE p.a = u.a

可以变成这样:

SELECT *
FROM
 (
  SELECT a.a1    A,
         a.a2    B
    FROM tab_a a,
         tab_p p
   WHERE p.a = a.a1
UNION ALL
  SELECT b.b1    A,
         b.b2    B
    FROM tab_b b,
         tab_p p
   WHERE p.a = b.b1
)

这两个查询是等价的,对吧?[编辑]

4

3 回答 3

3

查询将产生相同的结果集,但执行计划可能不同。我希望第一个查询更有效,因为它tab_p与第二个查询中的两次进行比较。


以前,两个查询都使用 SELECT *,其中任何一个都没有表别名。

不,这些查询是不等价的。

第一个将从派生表(UNION'd 语句)和tab_p表中返回列。第二个查询将只返回派生表(UNION'd 语句)中的值,而不返回表中的列tab_p。如果您将表别名替换为SELECT *

第一个查询:

SELECT u.*, p.*
  FROM (SELECT a.a1    A,
               a.a2    B
          FROM tab_a a
        UNION ALL
        SELECT b.b1    A,
               b.b2    B
          FROM tab_b b) u,
       tab_p p
 WHERE p.a = u.a

第二个查询:

SELECT x.*
 FROM (SELECT a.a1    A,
              a.a2    B
         FROM tab_a a,
              tab_p p
        WHERE p.a = a.a
       UNION ALL
       SELECT b.b1    A,
              b.b2    B
         FROM tab_b b,
              tab_p p
        WHERE p.a = b.a) x

内部查询的 SELECT 子句中没有tab_p列,供外部查询在最终结果集中提供。

这:

SELECT *
  FROM (SELECT a.a1    A,
               a.a2    B
          FROM tab_a a
        UNION ALL
        SELECT b.b1    A,
               b.b2    B
          FROM tab_b b) u
  JOIN tab_p p ON p.a = u.a

..相当于第一个查询。它使用 ANSI-92 连接语法与第一个查询中使用的 ANSI-89 语法。

于 2010-09-28T19:19:05.703 回答
2

您在编辑的问题中描述的转换对我来说似乎有效。

Oracle 优化器理论上可以执行许多不同的查询转换,但实际上这仅限于 Oracle 团队实际费心实施的那些转换。

如果添加每个转换,则需要在编码和测试方面进行大量投资,并且只有在付费市场中检测到足够的需求时才会进行。

所以,不一定是它“不能”;它只是还没有。

于 2010-09-29T03:08:25.947 回答
0

它们不是等价的。第二个查询将失败,因为u未定义。

于 2010-09-28T19:18:37.177 回答