SqlDatabaseIntermediate

RIGHT JOIN

Returns all rows from the right table, plus matching rows from the left.

Review the syntaxStudy the examplesOpen the coding app
SELECT columns FROM left_table RIGHT JOIN right_table ON left_table.id = right_table.fk_id;

This static page keeps the syntax and examples indexed for search, while the coding app handles interactive exploration and saved references.

What it does

Overview

Returns all rows from the right table, plus matching rows from the left.

The RIGHT JOIN (or RIGHT OUTER JOIN) keyword returns all records from the right table (table2), and the matching records from the left table (table1). If there is no match for a specific row in the right table, the resulting columns from the left table will contain NULL values. While functionally equivalent to a LEFT JOIN with the table order reversed, RIGHT JOIN is used less frequently in professional environments because most developers find a 'starting table' (left-to-right) mental model more intuitive for query logic. From a performance perspective, modern query optimizers (such as those in PostgreSQL, MySQL, or SQL Server) typically treat RIGHT JOIN and LEFT JOIN identically by transforming the execution plan into the most efficient join type (e.g., Hash Join or Merge Join). However, an important edge case occurs when using the WHERE clause: if you filter on a column from the left table that is not part of the join condition, you may unintentionally filter out the NULLs produced by the RIGHT JOIN, effectively converting the operation into an INNER JOIN. For best performance, ensure that the columns used in the ON clause are indexed.

Quick reference

Syntax

SELECT columns FROM left_table RIGHT JOIN right_table ON left_table.id = right_table.fk_id;

Inputs

Parameters

left_tableLeft side table (matched rows included).
right_tableRight side table (all rows preserved).
ON conditionJoin condition defining the relationship.

See it in practice

Examples

1

Basic RIGHT JOIN for Department Coverage

SELECT employees.name, departments.dept_name
FROM employees
RIGHT JOIN departments
ON employees.dept_id = departments.id;
Output:
| name | dept_name | |---|---| | Alice | Sales | | Bob | Engineering | | NULL | Marketing |

Returns all departments, including 'Marketing' which currently has no assigned employees (resulting in a NULL name).

2

Identifying 'Orphan' Records in the Right Table

SELECT d.dept_name
FROM employees e
RIGHT JOIN departments d
ON e.dept_id = d.id
WHERE e.id IS NULL;
Output:
| dept_name | |---| | Marketing |

Uses a RIGHT JOIN combined with a NULL check to find departments that do not have any associated employees.

3

Right Join Across Regional Data

SELECT r.region_name, d.dept_name
FROM departments d
RIGHT JOIN regions r
ON d.region_id = r.id
ORDER BY r.region_name ASC;
Output:
| region_name | dept_name | |---|---| | EMEA | Sales | | LATAM | NULL | | NA | Engineering |

Ensures every region is listed in the final report, even if no departments are currently operational in that specific region.

Debug faster

Common Errors

1

LogicError

Cause: Using a WHERE clause on the left table's columns that does not account for NULLs, which forces the query to act like an INNER JOIN.

Fix: Move the condition to the ON clause or explicitly check for NULL in the WHERE clause.

-- Bad: Removes the NULL rows generated by the RIGHT JOIN
SELECT * FROM employees e RIGHT JOIN departments d ON e.dept_id = d.id WHERE e.status = 'Active';
2

AmbiguousColumnError

Cause: Selecting columns that exist in both the left and right tables without using table aliases.

Fix: Always prefix column names with table names or aliases (e.g., table_a.id).

-- Bad: If both tables have an 'id' column
SELECT id FROM table_a RIGHT JOIN table_b ON table_a.fk = table_b.id;

Runtime support

Compatibility

Most SQL databasesSQL-92 (Standard)

SQLite does not support RIGHT JOIN (rewrite as LEFT JOIN)

Source: MDN Web Docs

Common questions

Frequently Asked Questions

Returns all rows from the right table, plus matching rows from the left.

able: Left side table (matched rows included). able: Right side table (all rows preserved). ON condition: Join condition defining the relationship.

LogicError: Move the condition to the ON clause or explicitly check for NULL in the WHERE clause. AmbiguousColumnError: Always prefix column names with table names or aliases (e.g., .id).