Родственные связи данных в Python
Пусть перед нами стоит задача хранить отцов и сыновей. Пусть каждый отец может иметь только одного сына, а сын в свою очередь тоже может иметь одного сына.
Нужно придумать, как мы будем хранить
данные. Первая идея, которая может прийти
в голову - сделать две таблицы: parents
для отцов и sons
для сыновей. Затем
связать эти таблицы каким-нибудь полем:
son_id
или parent_id
.
Однако, это идея не очень хорошая - ведь один и тот же человек может быть одновременно и отцом и сыном - и придется хранить его в обоих таблицах, а это неудобно, занимает больше место и легко приводит к ошибкам.
Более хороший вариант - связать таблицу
саму с собой: сделаем таблицу users
,
в ней будем хранить всех юзеров и каждому
сделаем поле son_id
, в котором будет
храниться id
сына из этой же таблицы:
id | name | son_id |
---|---|---|
1 | user1 | 2 |
2 | user2 | 3 |
3 | user3 | null |
Запросы
Давайте теперь напишем запрос, который достанет юзера вместе с его сыном.
Для начала давайте просто достанем юзеров:
SELECT
*
FROM
users
Теперь заджойним к юзерам их сыновей. Джойнить мы будем таблицу саму к себе, поэтому нам нужно выполнить ее переименование:
LEFT JOIN users as sons
Теперь мы можем указать связь основой таблицы и переименованной:
LEFT JOIN users as sons ON sons.id=users.son_id
Укажем теперь поля:
SELECT
users.name as user_name, sons.name as son_name
Соберем все вместе и получим следующий запрос:
SELECT
users.name as user_name, sons.name as son_name
FROM
users
LEFT JOIN users as sons ON sons.id=users.son_id
Практические задачи
Пусть у нас есть категории. Каждая категория может принадлежать родительской категории, та в свою очередь своей родительской и так далее. Распишите структуру хранения.
Напишите запрос, который достанет категорию вместе с ее родительской категорией.
Напишите запрос, который достанет категорию вместе с ее родителем и прародителем.
Напишите запрос, который достанет категорию вместе с ее родителем, прародителем и прапрародителем.