SQL - INTERSECT Operator
SQL - The INTERSECT Operator
Section titled “SQL - The 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.
Understanding the INTERSECT Operator
Section titled “Understanding the INTERSECT Operator”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
SELECTstatements must be the same. - The order of the columns in both
SELECTstatements must be the same. - The data types of the corresponding columns must be compatible (e.g., you can compare an
INTwith aSMALLINT, but not with aVARCHAR).
Syntax
Section titled “Syntax”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.
Practical Example: Finding Top Employees
Section titled “Practical Example: Finding Top Employees”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 employeesCREATE 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 quarterCREATE 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 employeeNow, we use INTERSECT to find the employees who are in both tables:
SELECT EmployeeID, FullName, Department FROM ActiveEmployeesINTERSECTSELECT EmployeeID, FullName, Department FROM QuarterlyHighPerformers;Output
Section titled “Output”The query returns only the employees present in both lists:
| EmployeeID | FullName | Department |
|---|---|---|
| 101 | Alice Johnson | Sales |
| 103 | Charlie Brown | Sales |
Combining INTERSECT with Other Clauses
Section titled “Combining INTERSECT with Other Clauses”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.
Example with WHERE
Section titled “Example with WHERE”Let’s find the active high performers who are specifically in the ‘Sales’ department.
SELECT EmployeeID, FullName, Department FROM ActiveEmployeesWHERE Department = 'Sales'
INTERSECT
SELECT EmployeeID, FullName, Department FROM QuarterlyHighPerformersWHERE 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.
Alternative 1: Using INNER JOIN
Section titled “Alternative 1: Using INNER JOIN”An INNER JOIN is a common and efficient way to find matching rows.
SELECT DISTINCT T1.EmployeeID, T1.FullName, T1.DepartmentFROM ActiveEmployees AS T1INNER 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).
Alternative 2: Using IN with a Subquery
Section titled “Alternative 2: Using IN with a Subquery”This approach is often more readable when you only need to check for the existence of a key in another table.
SELECT EmployeeID, FullName, DepartmentFROM ActiveEmployeesWHERE EmployeeID IN (SELECT EmployeeID FROM QuarterlyHighPerformers);Common Mistakes and Debugging
Section titled “Common Mistakes and Debugging”- Column Mismatch: The most common error is having a different number of columns or incompatible data types in the
SELECTlists. Always double-check that your selected columns align perfectly. - Performance Issues: On very large datasets,
INTERSECTcan be slow as the database needs to process and compare two full result sets. If performance is critical, testing an equivalentINNER JOINorEXISTSquery is a good practice. Use your database’sEXPLAINcommand to compare query plans. - Forgetting Alternatives: Developers accustomed to PostgreSQL or SQL Server might forget that
INTERSECTisn’t universally supported. Knowing theJOINorINalternatives is essential for writing portable code.