~={yellow}Основные виды JOIN=~
~={yellow}Создадим таблицы для тестов=~
drop table if exists book_category, author, book cascade;
create table author (
author_id bigint generated always as identity primary key,
name varchar(150) not null check (length(name) >= 3),
description text check (length(description) >= 30)
);
create table book_category (
category_id int generated always as identity primary key,
name varchar(150) not null check (length(name) >= 2)
);
create table book (
book_id bigint generated always as identity primary key,
name varchar(255) not null check (length(name) >= 2),
author_id bigint references author(author_id),
description text check (length(description) >= 30),
cover varchar(255),
category_id int references book_category(category_id),
created_at timestamp
);
INSERT INTO book_category ("name") VALUES
('Художественая литература'),
('Литература по программированию'),
('Литература по фотографии');
INSERT INTO author ("name",description) VALUES
('Михаил Шолохов','Великий русский советский писатель, журналист и киносценарист.'),
('Лусиану Рамальо','Автор замечательных книг по языку программирования Python.'),
('Александр Пушкин','Русский поэт, драматург и прозаик, рассматривается как основоположник современного русского литературного языка.'),
('Александр Беляев','Русский писатель-фантаст, один из основоположников советской научно-фантастической литературы.'),
('Жюль Верн','Французский писатель, классик приключенческой литературы, один из основоположников жанра научной фантастики.'),
('Борис Пастернак', 'Один из крупнейших русских поэтов XX века.');
INSERT INTO book ("name",author_id,description,cover,category_id,created_at) VALUES
('Тихий Дон',1,'Одно из наиболее значительных, масштабных и талантливых произведений русскоязычной литературы, принесшее автору Нобелевскую премию.','https://cdn.rroom.io/17558b4d-59dd-4f8e-b2c7-51b0d7da5216.png',1,'2024-01-01 00:00:00'),
('Python. К вершинам мастерства',2,'Лучшая книга по углубленному изучению Python.','https://cdn.rroom.io/2bee8345-a535-4fe3-add9-8db804ea89ae.png',2,'2024-01-02 00:00:00'),
('Судьба человека',1,'Пронзительный рассказ о временах Великой Отечественной войны, одно из первых произведений советской литературы, в котором война показана правдиво и наглядною.','https://cdn.rroom.io/271755e5-046f-4842-85cf-4e22cb17b294.png',1,'2024-01-03 00:00:00'),
('Капитанская дочка',3,NULL,NULL,1,'2024-01-04 00:00:00'),
('Сказка о рыбаке и рыбке',3,NULL,NULL,1,'2024-01-05 00:00:00'),
('Голова профессора Доуэля',4,NULL,NULL,1,'2024-01-06 00:00:00'),
('Остров погибших кораблей',4,NULL,NULL,1,'2024-01-07 00:00:00'),
('Путешествие к центру Земли',5,NULL,NULL,1,'2024-01-08 00:00:00'),
('Дети капитана Гранта',5,NULL,NULL,1,'2024-01-09 00:00:00'),
('Простой Python',NULL,NULL,NULL,NULL,'2024-01-10 00:00:00');
~={magenta}INNER JOIN=~ - это тип соединения таблиц, который возвращает строки, имеющие совпадения в обеих таблицах на основе указанного условия.
select b.name as book_name, a.name as author_name
from book b
inner join author a on b.author_id = a.author_id
order by author_name, book_name;
|book_name |author_name |
|-----------------------------|----------------|
|Голова профессора Доуэля |Александр Беляев|
|Остров погибших кораблей |Александр Беляев|
|Капитанская дочка |Александр Пушкин|
|Сказка о рыбаке и рыбке |Александр Пушкин|
|Дети капитана Гранта |Жюль Верн |
|Путешествие к центру Земли |Жюль Верн |
|Python. К вершинам мастерства|Лусиану Рамальо |
|Судьба человека |Михаил Шолохов |
|Тихий Дон |Михаил Шолохов |
|Тихий Дон. Том 1 |Михаил Шолохов |
|Тихий Дон. Том 2 |Михаил Шолохов |
~={yellow}Более короткая запись с использованием using=~
select b.name as book_name, a.name as author_name
from book b
inner join author a using(author_id)
order by author_name, book_name;
То есть вместо on b.author_id = a.author_id
можно писать using(author_id)
. Есть мнение, что это вообще хороший повод называть первичные ключи в таблицах именно так, название сущности, подчеркивание, id, вместо просто id.
То есть если бы в таблице авторов первичный ключ был бы не author_id
, а id
, то запрос пришлось бы писать только так:
select b.name as book_name, a.name as author_name
from book b
inner join author a on b.author_id = a.id
order by author_name, book_name;
При этом можно записать тот же запрос и в таком синтаксисе, вообще без JOIN
:
select b.name as book_name, a.name as author_name
from book b, author a
where b.author_id = a.author_id
order by author_name, book_name;