Skip to content

SQL - INTERSECT Operator

In relational databases, we often need to find common records between two different queries. The INTERSECT operator is a standard SQL set operator designed for this exact purpose. It returns only the rows that appear in the result sets of both SELECT statements.

Think of it like finding the overlapping section of two Venn diagrams. If one set represents customers who bought Product A and another set represents customers who bought Product B, INTERSECT would give you the list of customers who bought both.

The INTERSECT operator combines two SELECT statements and returns only the distinct rows that are common to both. For it to work correctly, a few rules must be followed:

  • The number of columns in both SELECT statements must be the same.
  • The order of the columns in both SELECT statements must be the same.
  • The data types of the corresponding columns must be compatible (e.g., you can compare an INT with a SMALLINT, but not with a VARCHAR).

The basic syntax for the INTERSECT operator is straightforward:

SELECT column1, column2, ... FROM table1
[WHERE condition1]
INTERSECT
SELECT column1, column2, ... FROM table2
[WHERE condition2];

Note: INTERSECT implicitly returns only distinct rows. If a row appears three times in the first result set and twice in the second, it will only appear once in the final output.

Let’s imagine we have two tables. ActiveEmployees lists all current employees, and QuarterlyHighPerformers lists employees who exceeded their targets this quarter. We want to find the high performers who are also currently active.

First, let’s create and populate our tables.

-- Table for all currently active employees
CREATE TABLE ActiveEmployees (
EmployeeID INT PRIMARY KEY,
FullName VARCHAR(100) NOT NULL,
Department VARCHAR(50)
);
INSERT INTO ActiveEmployees (EmployeeID, FullName, Department) VALUES
(101, 'Alice Johnson', 'Sales'),
(102, 'Bob Williams', 'Engineering'),
(103, 'Charlie Brown', 'Sales'),
(104, 'Diana Miller', 'Marketing');
-- Table for employees who were high performers this quarter
CREATE TABLE QuarterlyHighPerformers (
EmployeeID INT PRIMARY KEY,
FullName VARCHAR(100) NOT NULL,
Department VARCHAR(50)
);
INSERT INTO QuarterlyHighPerformers (EmployeeID, FullName, Department) VALUES
(101, 'Alice Johnson', 'Sales'),
(103, 'Charlie Brown', 'Sales'),
(105, 'Eve Davis', 'Engineering'); -- Eve is a former employee

Now, we use INTERSECT to find the employees who are in both tables:

SELECT EmployeeID, FullName, Department FROM ActiveEmployees
INTERSECT
SELECT EmployeeID, FullName, Department FROM QuarterlyHighPerformers;

The query returns only the employees present in both lists:

EmployeeIDFullNameDepartment
101Alice JohnsonSales
103Charlie BrownSales

You can use WHERE, ORDER BY, and other clauses with INTERSECT. WHERE clauses are applied to each SELECT statement individually before the intersection is calculated. An ORDER BY clause can be added at the very end to sort the final result set.

Let’s find the active high performers who are specifically in the ‘Sales’ department.

SELECT EmployeeID, FullName, Department FROM ActiveEmployees
WHERE Department = 'Sales'
INTERSECT
SELECT EmployeeID, FullName, Department FROM QuarterlyHighPerformers
WHERE Department = 'Sales';

This query will yield the same result as before, but it can be more efficient on large tables as it filters the data before performing the intersection.

Handling Databases Without INTERSECT (e.g., MySQL)

Section titled “Handling Databases Without INTERSECT (e.g., MySQL)”

Some popular database systems, like MySQL (prior to version 8), do not support the INTERSECT operator. In such cases, you can achieve the same result using an INNER JOIN or the IN operator.

An INNER JOIN is a common and efficient way to find matching rows.

SELECT DISTINCT T1.EmployeeID, T1.FullName, T1.Department
FROM ActiveEmployees AS T1
INNER JOIN QuarterlyHighPerformers AS T2 ON T1.EmployeeID = T2.EmployeeID;

The DISTINCT keyword is crucial here because INTERSECT returns unique rows, and a JOIN might produce duplicates if there are multiple matches (though not in this specific primary key example).

This approach is often more readable when you only need to check for the existence of a key in another table.

SELECT EmployeeID, FullName, Department
FROM ActiveEmployees
WHERE EmployeeID IN (SELECT EmployeeID FROM QuarterlyHighPerformers);
  • Column Mismatch: The most common error is having a different number of columns or incompatible data types in the SELECT lists. Always double-check that your selected columns align perfectly.
  • Performance Issues: On very large datasets, INTERSECT can be slow as the database needs to process and compare two full result sets. If performance is critical, testing an equivalent INNER JOIN or EXISTS query is a good practice. Use your database’s EXPLAIN command to compare query plans.
  • Forgetting Alternatives: Developers accustomed to PostgreSQL or SQL Server might forget that INTERSECT isn’t universally supported. Knowing the JOIN or IN alternatives is essential for writing portable code.