views:

75

answers:

3

I know Oracle RDMS can't merge a view that has a set operator in it. I want to know why is that.

For example, this:

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

could be transformed into this:

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
)

These two queries are equivalent, right? [edited]

A: 

They are not equivalent. The second query will fail, as u is not defined.

RedFilter
+2  A: 

The queries will produce the same resultset, but the execution plan is likely to be different. I would expect the first query to be more efficient because it is comparing against tab_p once, vs the two times in the second query.


Previously, both queries used SELECT *, no table alias in either of them.

No, those queries are not equivalent.

The first will return columns from both the derived table (UNION'd statement) and the tab_p table. The second query will only return values from the derived table (UNION'd statement), and no columns from the tab_p table. It's more obvious if you substitute the table aliases in the place of SELECT *:

First query:

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

Second query:

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

There are no tab_p columns in the SELECT clause of the inner query, for the outer query to provide in the ultimate resultset.

This:

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

..is equivalent to the first query. It's using ANSI-92 join syntax vs the ANSI-89 syntax used in the first query.

OMG Ponies
Ok, I've fixed this, now the first query selects only the union'd view. The question still remains.
milan
@milan: That's not fair to us to change the details of the question. We aren't notified about question changes, our answers risk being downvoted for not relating to the question. I realize it seems trivial, but proper etiquette is to mark an answer for the existing question and create a new question.
OMG Ponies
@OMG Ponies: just my 2c: I agree it's not nice if someone changes their question, but in this case, has the question been changed or just their syntax corrected? Anyway, as an upvoter/downvoter I do look at the question edits to see whether a downvote is really warranted, or if the answer just needs editing. Also, you do have the option of deleting your answer if it is no longer relevant :) (I've done this on a few occasions, where the original question was changed as the questioner understood their requirements better, and updated their question accordingly)
Jeffrey Kemp
@Jeffrey Kemp: Sure, but you're *sane* :)
OMG Ponies
@OMG Ponies: tables tab_a and tab_b could be huge and have high selectivity on columns a1 and b1 respectively, while tab_p could be small. Join columns are, normally, indexed. Oracle RDMS knows this facts because it has statistics. But, yeah that's also something I should have mentioned in the question. Although, the question is *why it can't* merge the view.
milan
@milan: Sorry, I haven't paid question titles too much attention to date. I don't see why Oracle would use something similar to predicate push for this situation--joining on the result afterwards is a single scan of `tab_p` vs the two (or more depending on the query) for the example. The optimizer algorithm is beyond me, though.
OMG Ponies
I the non-merged query, both huge tables have to be read in entirety.
milan
+2  A: 

The transformation you describe in your edited question appears valid to me.

There are many many many different query transformations that the Oracle optimizer could in theory perform, but in practice this is limited to those transformations that the Oracle team have actually bothered to implement.

Each transformation, if added, would require a significant investment in coding and testing, and would only be done if sufficient demand was detected in the paying market.

So, it's not that it "can't", necessarily; it just doesn't, yet.

Jeffrey Kemp