Соединение таблицы с собой онлайн урок.


В предыдущих уроках мы рассмотрели соединения таблиц. Возникает природный вопрос - можно ли соединять поля из одной таблицы? Ответ - можно.

Самый простой способ это сделать - записать дважды одну и туже таблицу после оператора FROM, но со специальными псевдонимами. Псевдоним для таблицы записывается через пробел после названия таблицы:

`group` g

Этот псевдоним нужен для того, чтобы система могла отличить две разные "копии" одной и той же таблицы. Заданные псевдонимы необходимо использовать как и обычные названия таблиц и их можно использовать при обозначении полей.

Напишем несложный запрос, который соединит данные из одной таблицы:

SELECT g1.description, g2.description FROM `group` g1, `group` g2;

Тут мы задали псевдонимы g1, g2 для таблицы group и обратились при помощи них к полям этой таблицы. Но, как уже было сказано в предыдущих уроках, такой запрос не имеет практической ценности - он возвращает все возможные комбинации значений поля description с собой
+-------------+-------------+
| description | description |
+-------------+-------------+
| Mathematics | Mathematics |
| Physics | Mathematics |
| Biology | Mathematics |
| Chemistry | Mathematics |
. ... . ... .
. ... . ... .
. ... . ... .
| Mathematics | Chemistry |
| Physics | Chemistry |
| Biology | Chemistry |
| Chemistry | Chemistry |
+-------------+-------------+
16 rows in set (0.00 sec)

Для написания осмысленного запроса, разобьем группы на подгруппы. Это значит что у каждой группы может быть родительская группа. Например, группа по математике может делиться на геометрию и алгебру. Для этого потребуется новое поле parent_id, в котором будет нулевое значение, если это родительская группа или id родительcкой группы, если это дочерняя:

ALTER TABLE `group` ADD COLUMN parent_id TINYINT(2) DEFAULT 0;
+----+-----------+-------------+-----------+
| id | name | description | parent_id |
+----+-----------+-------------+-----------+
| 1 | ifka-33-M | Mathematics | 0 |
| 2 | satr-41-P | Physics | 0 |
| 3 | oskt-56-B | Biology | 0 |
| 4 | desm-81-C | Chemistry | 0 |
+----+-----------+-------------+-----------+

По умолчанию значения нулевые, т.к. нынешние группы - все родительские. Добавим две подгруппы по математике:

INSERT INTO `group` (name, description, parent_id)
VALUES ('ifkag-33-M', 'Geometry', 1), ('ifkaa-33-M', 'Algebra', 1);
+----+------------+-------------+-----------+
| id | name | description | parent_id |
+----+------------+-------------+-----------+
| 1 | ifka-33-M | Mathematics | 0 |
| 2 | satr-41-P | Physics | 0 |
| 3 | oskt-56-B | Biology | 0 |
| 4 | desm-81-C | Chemistry | 0 |
| 5 | ifkag-33-M | Geometry | 1 |
| 6 | ifkaa-33-M | Algebra | 1 |
+----+------------+-------------+-----------+

Теперь мы можем записать запрос, который вернет названия дочерних групп, если они есть, и названия родительских групп:

SELECT g1.description AS parent, g2.description AS child 
FROM `group` g1 LEFT JOIN `group` g2
ON (g1.id = g2.parent_id);
+-------------+----------+
| parent | child |
+-------------+----------+
| Mathematics | Geometry |
| Mathematics | Algebra |
| Physics | NULL |
| Biology | NULL |
| Chemistry | NULL |
| Geometry | NULL |
| Algebra | NULL |
+-------------+----------+
7 rows in set (0.00 sec)

Таким образом мы пересекли соединили поля из одной таблицы и получили результат, который невозможно получить без соединения.