Natural join in SQL

Not as popular as other type of joins (INNER, OUTER, etc.), a NATURAL JOIN allows to implicitly combine tables based on the same column names present in both of them.

Given 3 tables:

CREATE TABLE categories (
  category_id SERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL
);

CREATE TABLE brands (
  brand_id SERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  created_at TIMESTAMP NOT NULL
);

CREATE TABLE products (
  product_id SERIAL PRIMARY KEY,
  brand_id INT NOT NULL,
  category_id INT NOT NULL,
  title VARCHAR(255) NOT NULL,
  created_at TIMESTAMP NOT NULL,
  CONSTRAINT fk_brand FOREIGN KEY(brand_id) REFERENCES brands(brand_id),
  CONSTRAINT fk_category FOREIGN KEY(category_id) REFERENCES categories(category_id)
);

Natural join between products and categories gives:

SELECT products.*, categories.*
FROM products
NATURAL JOIN categories;
product_id brand_id category_id title created_at category_id name
1 1 1 Macbook Pro 2020-01-01 00:00:00 1 laptops
2 1 2 iPhone SE 2020-01-02 00:00:00 2 phones
3 1 3 iPad Air 2020-01-03 00:00:00 3 tablets
4 2 1 Pixelbook GO 2020-01-04 00:00:00 1 laptops
5 2 2 Pixel 5 2020-01-05 00:00:00 2 phones
6 3 1 Surface 3 2020-01-06 00:00:00 1 laptops

But similar join between products and brands:

SELECT products.*, brands.*
FROM products
NATURAL JOIN brands;

Gives only 1 record:

product_id brand_id category_id title created_at brand_id name created_at
1 1 1 Macbook Pro 2020-01-01 00:00:00 1 Apple 2020-01-01 00:00:00

It comes from the fact that both products and brands tables besides brand_id, have also created_at in common which is implicitly used by natural join.

Finding

One of the use cases where NATURAL JOIN might be useful is comparing 2 tables:

CREATE TABLE t1 (
  a INT,
  b INT
);

CREATE TABLE t2 (
  a INT,
  b INT
);
INSERT INTO t1 VALUES
  (1, 2),
  (3, 4),
  (5, 6);

INSERT INTO t2 VALUES
  (3, 4),
  (5, 6),
  (7, 8);

To find values that are present in table t1 but not in t2 and vice-versa, a natural full join might be handy:

SELECT *
FROM (
  SELECT 't1' AS t1, t1.* FROM t1
) t1
NATURAL FULL JOIN (
  SELECT 't2' AS t2, t2.* FROM t2
) t2
WHERE t1 IS NULL OR t2 IS NULL;

Result:

a b t1 t2
1 2 t1  
7 8   t2

Full join here, ensures that we have values present only in t1, only in t2 and in both tables. Then t1 IS NULL OR t2 IS NULL filters common ones out.

Full examples from the note can be found on dbfiddle.