parent
5b1fd1e0b8
commit
2cdeff349a
2 changed files with 245 additions and 14 deletions
@ -0,0 +1,245 @@ |
||||
--- |
||||
title: Combining Query Results |
||||
description: Learn how to use UNION, INTERSECT, and EXCEPT to combine results from multiple queries |
||||
order: 150 |
||||
type: lesson-challenge |
||||
setup: | |
||||
```sql |
||||
CREATE TABLE fiction_books ( |
||||
id INT PRIMARY KEY, |
||||
title VARCHAR(255), |
||||
author VARCHAR(255), |
||||
price DECIMAL(10, 2) |
||||
); |
||||
|
||||
CREATE TABLE non_fiction_books ( |
||||
id INT PRIMARY KEY, |
||||
title VARCHAR(255), |
||||
author VARCHAR(255), |
||||
price DECIMAL(10, 2) |
||||
); |
||||
|
||||
INSERT INTO fiction_books (id, title, author, price) |
||||
VALUES |
||||
(1, 'The Great Gatsby', 'F. Scott Fitzgerald', 24.99), |
||||
(2, '1984', 'George Orwell', 19.99), |
||||
(3, 'Pride and Prejudice', 'Jane Austen', 15.99), |
||||
(4, 'The Hobbit', 'J.R.R. Tolkien', 29.99), |
||||
(5, 'The Doors of Perception', 'Aldous Huxley', 12.99); |
||||
|
||||
INSERT INTO non_fiction_books (id, title, author, price) |
||||
VALUES |
||||
(1, 'A Brief History of Time', 'Stephen Hawking', 29.99), |
||||
(2, 'The Art of War', 'Sun Tzu', 19.99), |
||||
(3, 'Sapiens', 'Yuval Noah Harari', 24.99), |
||||
(4, 'Pride and Prejudice: A Study Guide', 'John Smith', 12.99), |
||||
(5, 'The Doors of Perception', 'Aldous Huxley', 12.99); |
||||
|
||||
CREATE TABLE summer_reads ( |
||||
id INT PRIMARY KEY, |
||||
title VARCHAR(255), |
||||
author VARCHAR(255), |
||||
price DECIMAL(10, 2) |
||||
); |
||||
|
||||
INSERT INTO summer_reads (id, title, author, price) |
||||
VALUES |
||||
(1, 'The Great Gatsby', 'F. Scott Fitzgerald', 24.99), |
||||
(2, 'Sapiens', 'Yuval Noah Harari', 24.99), |
||||
(3, 'The Art of War', 'Sun Tzu', 19.99); |
||||
``` |
||||
--- |
||||
|
||||
Sometimes you need to combine results from multiple queries into a single result set. SQL provides several set operations for this purpose: `UNION`, `UNION ALL`, `INTERSECT`, and `EXCEPT`. |
||||
|
||||
## UNION and UNION ALL |
||||
|
||||
`UNION` combines results from two or more queries and removes duplicates. `UNION ALL` does the same but keeps duplicates. |
||||
|
||||
I have setup the following two tables `fiction_books` and `non_fiction_books` with the following data: |
||||
|
||||
| id | title | author | price | |
||||
| --- | ----------------------- | ------------------- | ----- | |
||||
| 1 | The Great Gatsby | F. Scott Fitzgerald | 24.99 | |
||||
| 2 | 1984 | George Orwell | 19.99 | |
||||
| 3 | Pride and Prejudice | Jane Austen | 15.99 | |
||||
| 4 | The Hobbit | J.R.R. Tolkien | 29.99 | |
||||
| 5 | The Doors of Perception | Aldous Huxley | 12.99 | |
||||
|
||||
| id | title | author | price | |
||||
| --- | ---------------------------------- | ----------------- | ----- | |
||||
| 1 | A Brief History of Time | Stephen Hawking | 29.99 | |
||||
| 2 | The Art of War | Sun Tzu | 19.99 | |
||||
| 3 | Sapiens | Yuval Noah Harari | 24.99 | |
||||
| 4 | Pride and Prejudice: A Study Guide | John Smith | 12.99 | |
||||
| 5 | The Doors of Perception | Aldous Huxley | 12.99 | |
||||
|
||||
### UNION Example |
||||
|
||||
Let's find all books across fiction and non-fiction categories: |
||||
|
||||
```sql |
||||
SELECT title, author, price |
||||
FROM fiction_books |
||||
UNION |
||||
SELECT title, author, price |
||||
FROM non_fiction_books |
||||
ORDER BY title; |
||||
``` |
||||
|
||||
The query above will combine the results from both the queries and remove any duplicates. Output will be: |
||||
|
||||
| title | author | price | |
||||
| ---------------------------------- | ------------------- | ----- | |
||||
| 1984 | George Orwell | 19.99 | |
||||
| A Brief History of Time | Stephen Hawking | 29.99 | |
||||
| Pride and Prejudice | Jane Austen | 15.99 | |
||||
| Pride and Prejudice: A Study Guide | John Smith | 12.99 | |
||||
| Sapiens | Yuval Noah Harari | 24.99 | |
||||
| The Art of War | Sun Tzu | 19.99 | |
||||
| The Doors of Perception | Aldous Huxley | 12.99 | |
||||
| The Great Gatsby | F. Scott Fitzgerald | 24.99 | |
||||
| The Hobbit | J.R.R. Tolkien | 29.99 | |
||||
|
||||
Notice how the `The Doors of Perception` book is only listed once even though it appears in both the `fiction_books` and `non_fiction_books` tables. |
||||
|
||||
### UNION ALL Example |
||||
|
||||
If you want to keep duplicates, use UNION ALL: |
||||
|
||||
```sql |
||||
SELECT title, author, price FROM fiction_books |
||||
UNION ALL |
||||
SELECT title, author, price FROM non_fiction_books |
||||
ORDER BY title; |
||||
``` |
||||
|
||||
The result will be: |
||||
|
||||
| title | author | price | |
||||
| ---------------------------------- | ------------------- | ----- | |
||||
| 1984 | George Orwell | 19.99 | |
||||
| A Brief History of Time | Stephen Hawking | 29.99 | |
||||
| Pride and Prejudice | Jane Austen | 15.99 | |
||||
| Pride and Prejudice: A Study Guide | John Smith | 12.99 | |
||||
| Sapiens | Yuval Noah Harari | 24.99 | |
||||
| The Art of War | Sun Tzu | 19.99 | |
||||
| The Doors of Perception | Aldous Huxley | 12.99 | |
||||
| The Doors of Perception | Aldous Huxley | 12.99 | |
||||
| The Great Gatsby | F. Scott Fitzgerald | 24.99 | |
||||
| The Hobbit | J.R.R. Tolkien | 29.99 | |
||||
|
||||
Notice how the `The Doors of Perception` book is listed twice. |
||||
|
||||
## INTERSECT |
||||
|
||||
`INTERSECT` returns only the rows that appear in both result sets. Let's find books that are in both the `fiction_books` and `non_fiction_books` tables: |
||||
|
||||
```sql |
||||
SELECT title, author FROM fiction_books |
||||
INTERSECT |
||||
SELECT title, author FROM non_fiction_books; |
||||
``` |
||||
|
||||
This will return: |
||||
|
||||
| title | author | |
||||
| ----------------------- | ------------- | |
||||
| The Doors of Perception | Aldous Huxley | |
||||
|
||||
## EXCEPT |
||||
|
||||
`EXCEPT` returns rows from the first query that don't appear in the second query. Let's find the books in the `fiction_books` table that aren't in the `non_fiction_books` table: |
||||
|
||||
```sql |
||||
SELECT title, author FROM fiction_books |
||||
EXCEPT |
||||
SELECT title, author FROM non_fiction_books |
||||
ORDER BY title; |
||||
``` |
||||
|
||||
This will return: |
||||
|
||||
| title | author | |
||||
| ------------------- | ------------------- | |
||||
| 1984 | George Orwell | |
||||
| Pride and Prejudice | Jane Austen | |
||||
| The Great Gatsby | F. Scott Fitzgerald | |
||||
| The Hobbit | J.R.R. Tolkien | |
||||
|
||||
--- |
||||
|
||||
## Requirements |
||||
|
||||
The key requirement for all of these set operation queries listed above is that the columns in both queries must have the same number, order, and data types. |
||||
|
||||
For example, below is an invalid query: |
||||
|
||||
```sql |
||||
-- ERROR: each UNION query must have the same number of columns |
||||
SELECT title, author FROM fiction_books |
||||
UNION |
||||
SELECT title, author, price FROM non_fiction_books; |
||||
``` |
||||
|
||||
Because the `fiction_books` table has 2 columns and the `non_fiction_books` table has 3 columns, the query will return an error. |
||||
|
||||
Similary if we try to combine the following two queries: |
||||
|
||||
```sql |
||||
-- ERROR: UNION types numeric and character varying cannot be matched |
||||
SELECT title, price FROM fiction_books |
||||
UNION |
||||
SELECT title, author FROM non_fiction_books; |
||||
``` |
||||
|
||||
This will also return an error because the `price` column from the first query doesn't have the same data type as the `author` column from the second query. |
||||
|
||||
## Challenge Time! 🎯 |
||||
|
||||
Using the provided tables, write queries to: |
||||
|
||||
1. Find all books that cost exactly $19.99 across all categories |
||||
2. List authors who have written both fiction and non-fiction books |
||||
3. Find summer reads that aren't in our fiction collection |
||||
|
||||
<details> |
||||
<summary>Solution</summary> |
||||
|
||||
```sql |
||||
-- 1. Books that cost $19.99 |
||||
SELECT title, author, 'Fiction' as category |
||||
FROM fiction_books |
||||
WHERE price = 19.99 |
||||
UNION |
||||
SELECT title, author, 'Non-Fiction' as category |
||||
FROM non_fiction_books |
||||
WHERE price = 19.99; |
||||
|
||||
-- 2. Authors in both categories |
||||
SELECT author FROM fiction_books |
||||
INTERSECT |
||||
SELECT author FROM non_fiction_books; |
||||
|
||||
-- 3. Summer reads not in fiction |
||||
SELECT title, author FROM summer_reads |
||||
EXCEPT |
||||
SELECT title, author FROM fiction_books; |
||||
``` |
||||
|
||||
</details> |
||||
|
||||
## Key Takeaways |
||||
|
||||
- Use UNION to combine results and remove duplicates |
||||
- Use UNION ALL when you want to keep duplicates (it's faster than UNION) |
||||
- Use INTERSECT to find common rows between results |
||||
- Use EXCEPT to find rows in one result that aren't in another |
||||
- Column count, order, and data types must match across queries |
||||
- These operations are particularly useful when working with similar but separate data sets |
||||
|
||||
Remember: Choose the appropriate set operation based on your needs: |
||||
|
||||
- UNION/UNION ALL for combining results |
||||
- INTERSECT for finding common elements |
||||
- EXCEPT for finding differences |
Loading…
Reference in new issue