devugur

Day 4 - Joining tables

23 Aug 2025


Today we will learn about joining multiple tables in postgresql.

Why?

We join tables in databases because most real-world data is spread across multiple tables to avoid redundancy and improve organization. A single table usually doesn’t contain all the information you need for a query. Joining tables allows you to combine related data in meaningful ways.

-- see all the tables in the database
select
	table_name
from
	information_schema.tables
where
	table_schema = 'public';

We currently have only users table. Imagine each user having several travels. We need to store those travel objects in another table and connect them with a user.

Creating travels table

We will create another table to store travels.

create table travels (
	id SERIAL primary key,
	user_id INTEGER not null references users(id),
	destination_city VARCHAR(100) not null,
	destination_country VARCHAR(100) not null,
	travel_date DATE not null,
	return_date DATE,
	travel_type VARCHAR(50) default 'vacation',
	budget DECIMAL(10, 2),
	notes TEXT,
	status VARCHAR(20) default 'planned',
	created_at TIMESTAMP default CURRENT_TIMESTAMP,
	updated_at TIMESTAMP default CURRENT_TIMESTAMP
);

Note that we have a column called user_id which is an INTEGER and not null and references user's id. While connecting tables, we use references keyword and target_table(target_column).

Insert travels

insert into travels
	(user_id, destination_city, destination_country, travel_date, return_date, travel_type, budget, status)
values
	(2, 'Tokyo', 'Japan', '2025-09-15', '2025-09-22', 'vacation', 2000, 'planned');

Note that we are providing user_id while inserting a travel so that we are connecting the travel object with a user with the id of 2.

You can create mock data using mockaroo and import by following methods that we mentioned in day-2.

Querying with a join

Select users with their travel destinations.

select
	u.first_name,
	string_agg(t.destination_city, ', ') as destinations
from
	users as u
join travels as t
    on
	t.user_id = u.id
where
	u.first_name is not null
group by
	u.first_name;

Join types

Inner join is the most common join type and join is the shorthand for inner join.

  • INNER = only matching pairs.
  • LEFT/RIGHT = keep everything from one side, fill with NULLs if no match.
  • FULL = keep everything from both.
  • CROSS = everything with everything.

End of Day 4

Today we learned about joining tables.

Tomorrow we will learn about schemas and why they do exist.