Summary: in this tutorial, you’ll learn how to use PostgreSQL NATURAL JOIN
to join tables based on columns with the same names.
An Insight Into PostgreSQL NATURAL JOIN #
In PostgreSQL, a NATURAL JOIN
allows you to join tables based on columns with the same names in both tables.
Here’s the syntax of the NATURAL JOIN
:
SELECT select_list
FROM table1
NATURAL [INNER, LEFT, RIGHT, FULL] JOIN table2;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
In this syntax:
The NATURAL JOIN
joins two tables, table1
and table2
. These tables need the same column name and compatible types for matching.
The NATURAL JOIN
can be INNER JOIN
, LEFT JOIN
, RIGHT JOIN
, and FULL JOIN
.
If you don’t specify a join after the NATURAL
keyword, PostgreSQL will use an INNER JOIN
by default. If table1
and table2
have no common column, the NATURAL JOIN
behaves like a CROSS JOIN
.
Setting up sample tables #
First, create a new table called brands
:
CREATE TABLE brands (
brand_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
brand_name VARCHAR(255) NOT NULL
);
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Second, insert rows into the brands
table:
INSERT INTO
brands (brand_name)
VALUES
('Apple'),
('Samsung'),
('Google')
RETURNING *;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Output:
brand_id | brand_name
----------+------------
1 | Apple
2 | Samsung
3 | Google
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Third, create a new table called products
:
CREATE TABLE products (
product_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
brand_id INT,
FOREIGN KEY (brand_id) REFERENCES brands (brand_id)
);
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Finally, insert rows into the products
table:
INSERT INTO
products (product_name, price, brand_id)
VALUES
('iPhone 14 Pro', 999.99, 1),
('iPhone 15 Pro', 1199.99, 1),
('Galaxy S23 Ultra', 1149.47, 2),
('Oppo Find Flip', 499.99, NULL)
RETURNING *;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Output:
product_id | product_name | price | brand_id
------------+------------------+---------+----------
1 | iPhone 14 Pro | 999.99 | 1
2 | iPhone 15 Pro | 1199.99 | 1
3 | Galaxy S23 Ultra | 1149.47 | 2
4 | Oppo Find Flip | 499.99 | NULL
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
PostgreSQL NATURAL JOIN examples #
We’ll use NATURAL JOIN
to join the brands
and products
tables.
INNER JOIN #
The following statement uses a NATURAL JOIN
to perform an INNER JOIN
between the products
and brands
tables:
SELECT
product_name,
price,
brand_name
FROM
products
NATURAL INNER JOIN brands;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Output:
product_name | price | brand_name
------------------+---------+------------
iPhone 14 Pro | 999.99 | Apple
iPhone 15 Pro | 1199.99 | Apple
Galaxy S23 Ultra | 1149.47 | Samsung
Code language: plaintext (plaintext)
LEFT JOIN #
The following example uses a NATURAL JOIN
to join the products and brands tables using a LEFT JOIN
:
SELECT
product_name,
price,
brand_name
FROM
products
NATURAL LEFT JOIN brands;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Output:
product_name | price | brand_name
------------------+---------+------------
iPhone 14 Pro | 999.99 | Apple
iPhone 15 Pro | 1199.99 | Apple
Galaxy S23 Ultra | 1149.47 | Samsung
Oppo Find Flip | 499.99 | NULL
Code language: plaintext (plaintext)
RIGHT JOIN #
The following statement uses a NATURAL JOIN
to join the products
and brands
tables using a RIGHT JOIN
:
SELECT
product_name,
price,
brand_name
FROM
products
NATURAL RIGHT JOIN brands;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Output:
product_name | price | brand_name
------------------+---------+------------
iPhone 14 Pro | 999.99 | Apple
iPhone 15 Pro | 1199.99 | Apple
Galaxy S23 Ultra | 1149.47 | Samsung
NULL | NULL | Google
Code language: plaintext (plaintext)
FULL JOIN #
The following example uses a NATURAL JOIN
to join the products
and brands
tables using a FULL JOIN
:
SELECT
product_name,
price,
brand_name
FROM
products
NATURAL FULL JOIN brands;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Output:
product_name | price | brand_name
------------------+---------+------------
iPhone 14 Pro | 999.99 | Apple
iPhone 15 Pro | 1199.99 | Apple
Galaxy S23 Ultra | 1149.47 | Samsung
Oppo Find Flip | 499.99 | NULL
NULL | NULL | Google
Code language: plaintext (plaintext)
PostgreSQL NATURAL JOIN caveats #
PostgreSQL NATURAL JOIN
relies on the same column names for matching rows. If you change the table structure, the query may work differently than expected. For example:
DROP TABLE products, brands;
CREATE TABLE brands (
brand_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE products (
product_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
brand_id INT,
FOREIGN KEY (brand_id) REFERENCES brands (brand_id)
);
INSERT INTO
brands (name)
VALUES
('Apple'),
('Samsung'),
('Google')
RETURNING *;
INSERT INTO
products (name, price, brand_id)
VALUES
('iPhone 14 Pro', 999.99, 1),
('iPhone 15 Pro', 1199.99, 1),
('Galaxy S23 Ultra', 1149.47, 2),
('Oppo Find Flip', 499.99, NULL)
RETURNING *;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
We expect the following query to use the brand_id
column for joining the two tables:
SELECT
p.name product_name,
p.price,
b.name brand_name
FROM
products p
NATURAL INNER JOIN brands b;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
However, it returns an empty set:
product_name | price | brand_name
--------------+-------+------------
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
The reason is that the products
and brands
tables have the same brand_id
and name
columns.
In this case, the NATURAL JOIN
uses the values from both brand_id
and name
columns for matching rows. The NATURAL JOIN
behaves like the following query:
SELECT
p.name product_name,
p.price,
b.name brand_name
FROM
products p
INNER JOIN brands b ON b.brand_id = p.brand_id
AND b.name = p.name;
Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)
Since product names differ from brand names, the join condition is false, which causes the query to return an empty set.
Summary #
- PostgreSQL
NATURAL JOIN
uses common column names to join two tables based on common columns. - Use
NATURAL JOIN
with caution.