COMBINING QUERIES
Most SQL queries contain a single SELECT statement that
returns data from one or more tables. MySQL also enables you to
perform multiple queries (multiple SELECT statements) and
return the results as a single query result set. These combined
queries are usually known as unions or compound queries.
There are basically two scenarios in which you'd use combined
queries:
- To return similarly structured data from different
tables in a single query.
- To perform multiple queries against a single table
returning the data as one query.
Understanding Combined Queries
Most SQL queries contain a single SELECT statement that
returns data from one or more tables. MySQL also enables you to
perform multiple queries (multiple SELECT statements) and
return the results as a single query result set. These combined
queries are usually known as unions or compound queries.
There are basically two scenarios in which you'd use
combined queries:
- To return similarly structured data from different
tables in a single query
- To perform multiple queries against a single table
returning the data as one query
Tip
Combining Queries and Multiple
WHERE Conditions For the most part, combining two queries to
the same table accomplishes the same thing as a single query
with multiple WHERE clause conditions. In other words, any
SELECT statement with multiple WHERE clauses can also be
specified as a combined query, as you'll see in the section
that follows. The performance of each of the two techniques,
however, can vary based on the queries used. As such, it is
always good to experiment to determine which is preferable for
specific queries.
Creating Combined Queries
SQL queries are combined using the UNION operator. Using
UNION, multiple SELECT statements can be specified, and their
results can be combined into a single result set.
Using UNION
Using UNION is simple enough. All you do is specify each
SELECT statement and place the keyword UNION between each.
Let's look at an example. You need a list of all products
costing 5 or less. You also want to include all products made
by vendors 1001 and 1002, regardless of price. Of course, you
can create a WHERE clause that will do this, but this time
you'll use a UNION instead.
As just explained, creating a UNION involves writing
multiple SELECT statements. First look at the individual
statements:
• Input
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5;

• Output
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
| 1003 | FC | 2.50 |
| 1002 | FU1 | 3.42 |
| 1003 | SLING | 4.49 |
| 1003 | TNT1 | 2.50 |
+---------+---------+------------+
• Input
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001,1002);

• Output
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
| 1001 | ANV01 | 5.99 |
| 1001 | ANV02 | 9.99 |
| 1001 | ANV03 | 14.99 |
| 1002 | FU1 | 3.42 |
| 1002 | OL1 | 8.99 |
+---------+---------+------------+
• Analysis
The first SELECT retrieves all products with a price of no
more than 5. The second SELECT uses IN to find all products
made by vendors 1001 and 1002.
To combine these two statements, do the following:
• Input
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001,1002);

• Output
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
| 1003 | FC | 2.50 |
| 1002 | FU1 | 3.42 |
| 1003 | SLING | 4.49 |
| 1003 | TNT1 | 2.50 |
| 1001 | ANV01 | 5.99 |
| 1001 | ANV02 | 9.99 |
| 1001 | ANV03 | 14.99 |
| 1002 | OL1 | 8.99 |
+---------+---------+------------+
• Analysis
The preceding statements are made up of both of the previous
SELECT statements separated by the UNION keyword. UNION
instructs MySQL to execute both SELECT statements and combine
the output into a single query result set.
As a point of reference, here is the same query using
multiple WHERE clauses instead of a UNION:
• Input
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
OR vend_id IN (1001,1002);

In this simple example, the UNION might actually be more
complicated than using a WHERE clause. But with more complex
filtering conditions, or if the data is being retrieved from
multiple tables (and not just a single table), the UNION could
have made the process much simpler.
UNION Rules
As you can see, unions are very easy to use. But a few rules
govern exactly which can be combined:
- A UNION must be comprised of two or more SELECT
statements, each separated by the keyword UNION (so, if
combining four SELECT statements, three UNION keywords
would be used).
- Each query in a UNION must contain the same columns,
expressions, or aggregate functions (although columns need
not be listed in the same order).
- Column datatypes must be compatible: They need not be
the exact same type, but they must be of a type that MySQL
can implicitly convert (for example, different numeric
types or different date types).
Aside from these basic rules and restrictions, unions can be
used for any data retrieval tasks.
Including or Eliminating Duplicate Rows
Go back to the preceding section titled "Using UNION" and
look at the sample SELECT statements used. You'll notice that
when executed individually, the first SELECT statement returns
four rows, and the second SELECT statement returns five rows.
However, when the two SELECT statements are combined with a
UNION, only eight rows are returned, not nine.
The UNION automatically removes any duplicate rows from the
query result set (in other words, it behaves just as multiple
WHERE clause conditions in a single SELECT would). Because
vendor 1002 creates a product that costs less than 5, that row
was returned by both SELECT statements. When the UNION was
used, the duplicate row was eliminated.
This is the default behavior of UNION, but you can change
this if you so desire. If you do, in fact, want all occurrences
of all matches returned, you can use UNION ALL instead of
UNION.
Look at the following example:
• Input
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION ALL
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001,1002);

• Output
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
| 1003 | FC | 2.50 |
| 1002 | FU1 | 3.42 |
| 1003 | SLING | 4.49 |
| 1003 | TNT1 | 2.50 |
| 1001 | ANV01 | 5.99 |
| 1001 | ANV02 | 9.99 |
| 1001 | ANV03 | 14.99 |
| 1002 | FU1 | 3.42 |
| 1002 | OL1 | 8.99 |
+---------+---------+------------+
• Analysis
Using UNION ALL, MySQL does not eliminate duplicates.
Therefore, the preceding example returns nine rows, one of them
occurring twice.
Tip
UNION versus WHERE The
beginning of this tutorial said that UNION almost always
accomplishes the same thing as multiple WHERE conditions. UNION
ALL is the form of UNION that accomplishes what cannot be done
with WHERE clauses. If you do, in fact, want all occurrences of
matches for every condition (including duplicates), you must
use UNION ALL and not WHERE.
Sorting Combined Query Results
SELECT statement output is sorted using the ORDER BY clause.
When combining queries with a UNION, only one ORDER BY clause
may be used, and it must occur after the final SELECT
statement. There is very little point in sorting part of a
result set one way and part another way, and so multiple ORDER
BY clauses are not allowed.
The following example sorts the results returned by the
previously used UNION:
• Input
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001,1002)
ORDER BY vend_id, prod_price;

• Output
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
| 1001 | ANV01 | 5.99 |
| 1001 | ANV02 | 9.99 |
| 1001 | ANV03 | 14.99 |
| 1002 | FU1 | 3.42 |
| 1002 | OL1 | 8.99 |
| 1003 | TNT1 | 2.50 |
| 1003 | FC | 2.50 |
| 1003 | SLING | 4.49 |
+---------+---------+------------+
• Analysis
This UNION takes a single ORDER BY clause after the final
SELECT statement. Even though the ORDER BY appears to only be a
part of that last SELECT statement, MySQL will in fact use it
to sort all the results returned by all the SELECT
statements.
Note
Combining Different Tables For the sake of simplicity,
all of the examples in this tutorial combined queries using the
same table. However, everything you learned here also applies
to using UNION to combine queries of different tables.
Summary
In this tutorial, you learned how to combine SELECT
statements with the UNION operator. Using UNION, you can return
the results of multiple queries as one combined query, either
including or excluding duplicates. The use of UNION can greatly
simplify complex WHERE clauses and retrieving data from
multiple tables.
[Next]
|