BC remote Oracle DBA - Call (800) 766-1884  
Oracle Consulting Oracle Training Development

Remote DBA

Remote DBA Plans  

Remote DBA Service

Remote DBA RAC

   
Remote DBA Oracle Home
Remote DBA Oracle Training
Remote DBA SQL Tuning Consulting
Remote DBA Oracle Tuning Consulting
Remote DBA Data Warehouse Consulting
Remote DBA Oracle Project Management
Remote DBA Oracle Security Assessment
Remote DBA Unix Consulting
Burleson Books
Burleson Articles
Burleson Web Courses
Burleson Qualifications
Oracle Links
Remote DBA Oracle Monitoring
Remote DBA Support Benefits
Remote DBA Plans & Prices
Our Automation Strategy
What We Monitor
Oracle Apps Support
Print Our Brochure
Contact Us (e-mail)
Oracle Job Opportunities
Oracle Consulting Prices





   

 

 

 

Remote DBA services

Remote DBA Support

Remote DBA RAC

Remote DBA Reasons

Remote Oracle Tuning

Remote DBA Links

Oracle DBA Support

Oracle DBA Forum

Oracle Disaster

Oracle Training

Oracle Tuning

Oracle Training

 Remote DBA SQL Server

Remote MSSQL Consulting

Oracle DBA Hosting

Oracle License Negotiation

 

 


 

 

 

 

 
 

EnterpriseDB: Complex Selects

Oracle Tips by Burleson Consulting
 

In the above section, we covered all of the basic parts of a query.  In this section, we will cover some of the less used, but just as important, complex SQL functionality.

The first up is the UNION keyword.  We could get into a deep philosophical discussion of the mathematics behind SQL, but it has been my experience that most people just aren't that interested.  So, I will use a new analogy.  I call it the pocket analogy.

Let's pretend that I am wearing pants.  That is something I do most times.  Now, let's further pretend that my pants have two pockets, one on my left and one on my right.

My left pocket, hypothetically, has 2 quarters ($0.25), 2 dimes ($0.10), and 3 pennies ($0.01).  My right pocket has 1 quarter, 3 dimes and 2 nickels ($0.05).  

Let's turn this into a couple of tables.  I'll create a left_table that represents my left pocket and a right_table that represents the right pocket.

To follow along with this example, run this code:

CREATE TABLE left_table (amount number);
CREATE TABLE right_table (amount number);
INSERT INTO left_table (amount) VALUES (.25);
INSERT INTO left_table (amount) VALUES (.25);
INSERT INTO left_table (amount) VALUES (.10);
INSERT INTO left_table (amount) VALUES (.10);
INSERT INTO left_table (amount) VALUES (.01);
INSERT INTO left_table (amount) VALUES (.01);
INSERT INTO left_table (amount) VALUES (.01);
INSERT INTO right_table (amount) VALUES (.25);
INSERT INTO right_table (amount) VALUES (.10);
INSERT INTO right_table (amount) VALUES (.10);
INSERT INTO right_table (amount) VALUES (.10);
INSERT INTO right_table (amount) VALUES (.05);
INSERT INTO right_table (amount) VALUES (.05);
COMMIT;

Ok, the UNION ALL of my left pocket and my right pocket would be represented as:

SELECT amount
  FROM left_table
UNION ALL
SELECT amount
  FROM right_table;

The output looks like:

edb=# SELECT amount
edb-#   FROM left_table
edb-# UNION ALL
edb-# SELECT amount
edb-#   FROM right_table; 

 amount
--------
   0.25
   0.25
   0.10

   
0.10
   0.01
   0.01
   0.01
   0.25
   0.10
   0.10
   0.10
   0.05
   0.05

(13 rows)

edb=#

So a union all will take all of the rows in the first table and UNION them (or include them in the result set) with all of the rows in the second table.

I am going to run this again, but this time I will do a UNION instead of a UNION ALL:

SELECT amount
  FROM left_table
UNION
SELECT amount
  FROM right_table; 

edb=# SELECT amount
edb-#   FROM left_table
edb-# UNION
edb-# SELECT amount
edb-#   FROM right_table;

 amount
--------
   0.01
   0.05
   0.10
   0.25

(4 rows)

edb=#

This did exactly the same thing as UNION ALL but UNION adds an additional step.  UNION sorts the output and removes duplicate rows. 

If you want to know about ALL of the rows in a UNION, use UNION ALL.  If you are interested in only distinct rows, use UNION.  The distinct part of the UNION applies to only those columns in your select list.  It also always applies to all columns in your select list.

Next up is the EXCEPT keyword.  EXCEPT will return a result that is the difference between two result sets.  Specifically, it will return those rows in the upper table that do not exist in the lower table.  If you are coming from an Oracle environment, EXCEPT is the EnterpriseDB equivalent of MINUS.

If we run this query:

SELECT amount
  FROM left_table
EXCEPT ALL
SELECT amount
  FROM right_table; 

edb=# SELECT amount
edb-#   FROM left_table
edb-# EXCEPT ALL
edb-# SELECT amount
edb-#   FROM right_table;

 amount
--------
   0.01
   0.01
   0.01
   0.25

(4 rows)

edb=#

No 0.01 records exist in the second query and only a single 0.25 exists so that is the result that is returned to us.  If we take off the ALL keyword, the SQL engine removes duplicates like in the UNION but it considers a duplicate to be any row that has a duplicate in the second parent table.

So if we run this query:

SELECT amount
  FROM left_table
EXCEPT
SELECT amount
  FROM right_table;

edb=# SELECT amount
edb-#   FROM left_table
edb-# EXCEPT
edb-# SELECT amount
edb-#   FROM right_table;

 amount
--------
   0.01

(1 row)

edb=#

If the lack of an ALL removes duplicates, you might wonder why the 0.25 went away.  The upper query had a 0.25 so in the second query, 0.25 was a duplicate.  The only value that did not exist in the lower query, which did exist in the upper query, was the 0.01.

Let's turn the query around and put the right table at the top and the left table on the bottom:

SELECT amount
  FROM right_table
EXCEPT
SELECT amount
  FROM left_table;

edb=# SELECT amount
edb-#   FROM right_table
edb-# EXCEPT
edb-# SELECT amount
edb-#   FROM left_table;

 amount
--------
   0.05

(1 row)

edb=#

Can you explain why the 0.05 is all that was returned?  The left_table did not contain any 0.05 so that's what was returned.  Try adding the ALL keyword to see what impact that has on the result set.

The last complex query that I will be covering is the INTERSECT keyword.  If you can grasp UNION and EXCEPT, INTERSECT will be a breeze.

INTERSECT returns all rows that are in both the upper query and the lower query.  ALL works in INTERSECT just as it does in UNION; it sorts the results and allows duplicates.

SELECT amount
  FROM left_table
INTERSECT ALL
SELECT amount
  FROM right_table;

edb=# SELECT amount
edb-#   FROM left_table
edb-# INTERSECT ALL
edb-# SELECT amount
edb-#   FROM right_table;

 amount
--------

  
0.10
  0.10
  0.25

(3 rows)

edb=#

Both queries contain 0.10 and 0.25 and they both contain at least two 0.10 and one 0.25.  Neither contains a 0.01 or a 0.05. 

If we remove the ALL:

SELECT amount
  FROM left_table
INTERSECT
SELECT amount
  FROM right_table;

edb=# SELECT amount
edb-#   FROM left_table
edb-# INTERSECT
edb-# SELECT amount
edb-#   FROM right_table;

 amount
--------

   0.10

 
  0.25

(2 rows)

edb=#

The duplicates were removed from the result set.



This is an excerpt from the book "EnterpriseDB: The Definitive Reference" by Rampant TechPress.


Expert Remote DBA

BC is America's oldest and largest Remote DBA Oracle support provider.  Get real Remote DBA experts, call
BC Remote DBA today.

 

 

Remote DBA Service
 

Oracle Tuning Book

 

Advance SQL Tuning Book 

BC Oracle support

Oracle books by Rampant

Oracle monitoring software

 

 

 

 

 

 

BC Remote Oracle Support

Remote DBA

Remote DBA Services

Copyright © 1996 -  2013 by Burleson. All rights reserved.

Oracle® is the registered trademark of Oracle Corporation.



Hit Counter