Oracle INTERSECT Operator Explained

In Oracle Database, the INTERSECT operator is used to create a compound query that returns the intersection of the results of the left and right SELECT statements. In other words, it combines two queries, but returns only those rows that are returned in both queries.

Example

Suppose we have the following tables:

SELECT * FROM Employees;
SELECT * FROM Customers;

Result:

EMPLOYEEIDEMPLOYEENAME
1Bart
2Jan
3Ava
4Rohit
5Monish
6Monish
7Monish
CUSTOMERIDCUSTOMERNAME
1Mia
2Rohit
3Peter
4Ava
5Monish
6Monish

We can use the INTERSECT operator to return employees that are also customers:

SELECT EmployeeName FROM Employees
INTERSECT
SELECT CustomerName FROM Customers;

Result:

EMPLOYEENAME
Ava
Monish
Rohit

So it returns only those values that appear in both the Employees table and the Customers table.

Oracle Database’s implementation of the INTERSECT operator returns distinct rows only. We can see this in the above example. It returns just one row for Monish, even though there are multiple employees and multiple customers with that name.

Some RDBMSs allow us to include duplicates in the result by accepting an optional ALL keyword with the INTERSECT operator, but Oracle isn’t one of them (at least, not at the time of writing). Neither is SQLite.

An Alternative Query

It’s possible to get the same result without using the INTERSECT operator. For example, we could rewrite our first example to this:

SELECT 
    DISTINCT EmployeeName
FROM Employees e
WHERE EXISTS (SELECT CustomerName FROM Customers c
WHERE e.EmployeeName = c.CustomerName);

Result:

EMPLOYEENAME
Rohit
Ava
Monish

Some Things to Remember

Note that the expressions must match in number and must be in the same data type group. Therefore, we can’t do the following:

SELECT EmployeeName FROM Employees
INTERSECT
SELECT CustomerId, CustomerName FROM Customers;

Result:

ORA-01789: query block has incorrect number of result columns

Or this:

SELECT EmployeeName FROM Employees
INTERSECT
SELECT CustomerId FROM Customers;

Result:

ORA-01790: expression must have same datatype as corresponding expression

Although, we can use functions like TO_CHAR() to convert a column to a suitable data type group:

SELECT EmployeeName FROM Employees
INTERSECT
SELECT TO_CHAR(CustomerId) FROM Customers;

Result:

no data found

In this case, no data was found because none of the CustomerId values matched any of the EmployeeName values. But if they did, then we’d see the matches.