Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Set Operations: INTERSECT and EXCEPT
SQL

Set Operations: INTERSECT and EXCEPT

Go beyond UNION and discover how to find overlapping or exclusive data across datasets using INTERSECT and EXCEPT.

While JOIN combines columns horizontally, set operators like INTERSECT and EXCEPT compare entire rows across two result sets. They are the SQL equivalent of set intersection and set difference from mathematics.

INTERSECT

INTERSECT returns only the rows that are present in both query results. Duplicates are automatically removed.

SELECT product_id FROM current_inventory
INTERSECT
SELECT product_id from incoming_shipment;

Use cases:

  • Find customers who bought in both Q1 and Q2.
  • Find employees who are also managers.
  • Identify common records between two data sources during migration.

EXCEPT (MINUS in Oracle)

EXCEPT returns rows from the first query that are not present in the second query. Duplicates are removed.

SELECT product_id FROM current_catalog
EXCEPT
SELECT product_id FROM discontinued_products;

Use cases:

  • Find products that were never sold.
  • Identify users who haven’t logged in.
  • Detect missing records in one system compared to another.

INTERSECT vs INNER JOIN

These can sometimes produce the same result, but they work differently:

  • INTERSECT compares entire rows (all columns must match).
  • INNER JOIN matches on a join condition (typically one or two columns) and combines columns from both sides.
-- INTERSECT: row must be identical in both tables
SELECT * FROM TableA INTERSECT SELECT * FROM TableB;

-- INNER JOIN: only one column needs to match
SELECT a.* FROM TableA a INNER JOIN TableB b ON a.id = b.id;

EXCEPT vs NOT IN / NOT EXISTS

EXCEPT is often a clearer alternative to NOT IN or NOT EXISTS:

-- Using NOT IN
SELECT id FROM customers WHERE id NOT IN (SELECT customer_id FROM orders);

-- Using EXCEPT (cleaner for simple cases)
SELECT id FROM customers
EXCEPT
SELECT customer_id FROM orders;

Caution: NOT IN behaves unexpectedly if the subquery contains NULLs — it returns zero rows. EXCEPT handles NULLs correctly.

INTERSECT and EXCEPT with ORDER BY

Place ORDER BY at the very end of the combined query:

SELECT product_id FROM warehouse_a
INTERSECT
SELECT product_id FROM warehouse_b
ORDER BY product_id;

Rules for Set Operators

  1. Both queries must have the same number of columns.
  2. Corresponding columns must have compatible data types.
  3. The column names in the result come from the first query.
  4. ORDER BY can only appear at the end of the entire set operation.

Q: Difference between INTERSECT and INNER JOIN?

A: INTERSECT compares entire rows (all columns must match) and returns rows from both queries. INNER JOIN matches rows based on a join condition (usually one or two key columns) and combines columns from both tables.

Q: When would you use EXCEPT instead of NOT IN?

A: EXCEPT is cleaner and handles NULLs correctly. NOT IN can fail if the subquery returns any NULL values — the entire query returns zero rows. EXCEPT and NOT EXISTS handle NULLs properly.

Q: Can INTERSECT be used on tables with different column names?

A: The columns don’t need the same names, but they must have the same number, order, and compatible data types. Column names from the first query are used in the result.

1. Find products in both warehouses.

SELECT product_id FROM warehouse_a
INTERSECT
SELECT product_id FROM warehouse_b;

2. Find customers who bought in both Q1 and Q2.

SELECT customer_id FROM q1_sales
INTERSECT
SELECT customer_id FROM q2_sales;

3. Find products never sold.

SELECT product_id FROM products
EXCEPT
SELECT product_id FROM sales;

4. Find users who never logged in.

SELECT user_id FROM users
EXCEPT
SELECT user_id FROM login_history;

5. Compare two tables for data migration validation.

-- Rows missing from the target
SELECT * FROM source_table
EXCEPT
SELECT * FROM target_table;

6. Find mismatched records between systems.

(SELECT id, name, balance FROM system_a
 EXCEPT
 SELECT id, name, balance FROM system_b)
UNION ALL
(SELECT id, name, balance FROM system_b
 EXCEPT
 SELECT id, name, balance FROM system_a);

My Private Notes

Notes are auto-saved locally to this device.