# Родственные связи данных в PHP

Пусть перед нами стоит задача хранить отцов и сыновей. Пусть каждый отец может иметь только одного сына, а сын в свою очередь тоже может иметь одного сына.

Нужно придумать, как мы будем хранить данные. Первая идея, которая может прийти в голову - сделать две таблицы: `parents` для отцов и `sons` для сыновей. Затем связать эти таблицы каким-нибудь полем: `son_id` или `parent_id`.

Однако, это идея не очень хорошая - ведь один и тот же человек может быть одновременно и отцом и сыном - и придется хранить его в обоих таблицах, а это неудобно, занимает больше место и легко приводит к ошибкам.

Более хороший вариант - связать таблицу саму с собой: сделаем таблицу `users`, в ней будем хранить всех юзеров и каждому сделаем поле `son_id`, в котором будет храниться `id` сына из этой же таблицы:

users
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`

## Практические задачи

Пусть у нас есть категории. Каждая категория может принадлежать родительской категории, та в свою очередь своей родительской и так далее. Распишите структуру хранения.

Напишите запрос, который достанет категорию вместе с ее родительской категорией.

Напишите запрос, который достанет категорию вместе с ее родителем и прародителем.

Напишите запрос, который достанет категорию вместе с ее родителем, прародителем и прапрародителем.

←→
↑