MySQL SELECT: JOIN таблиц

JOIN — запрос на объединение временное двух таблиц. При использовании MySQL SELECT JOIN применяется для объединения значений нескольких таблиц и поиска по ним одним запросом.

 

Цикл по принципам работы с MySQL, более ранние материалы:
  1. Вводная статья цикла
  2. Начало работы с MySQL и основные команды
  3. MySQL SELECT, выборка из таблиц MySQL
  4. Регулярные выражения в MySQL

 

 

MySQL SELECT: JOIN и выборка из двух и более таблиц

SQL — декларативный язык, основанный на реляционной алгебре — он имеет в качестве компонента оптимизатор запросов, преобразующий пользовательский ввод и находящий самый простой и быстрый способ выполнить запрос. Поскольку в основе реляционная алгебра все ее законы применимы к SQL и его имплементациям вроде MySQL. Среди них объединение элементов для того чтобы выполнить запрос на выборку или обновление данных по обоим их них. Это MySQL SELECT JOIN и его подвиды. Реляционная алгебра для понимания JOIN не нужна.

 

 

 

Выборка по нескольким условиям

Продолжим работу с двумя существующими таблицами и продемонстрируем как работают JOIN

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

 

SELECT name, age, city, PRICE FROM PEOPLE WHERE PRICE > 15000;

+———-+——+——————+——-+
| name | age | city | PRICE |
+———-+——+——————+——-+
| Alexandr | 28 | Moskow | 50000 |
| Viktor | 29 | Moskow | 45000 |
| Boris | 27 | Novosibirsk | 16000 |
| Olga | 18 | Moskow | 50000 |
| Nikolay | 24 | Sankt-Peterburg | 25000 |
| Sergey | 22 | Krasnodar | 17000 |
+———-+——+——————+——-+
6 rows in set (0.00 sec)

 

Можно осуществлять выборку по условию и не выводя в качестве результата само условие — значение поля PRICE в данном случае

 

SELECT name, age, city FROM PEOPLE WHERE PRICE > 15000;

+———-+——+——————+
| name | age | city |
+———-+——+——————+
| Alexandr | 28 | Moskow |
| Viktor | 29 | Moskow |
| Boris | 27 | Novosibirsk |
| Olga | 18 | Moskow |
| Nikolay | 24 | Sankt-Peterburg |
| Sergey | 22 | Krasnodar |
+———-+——+——————+
6 rows in set (0.00 sec)

 

 

Теперь перейдем к простейшему MySQL SELECT JOIN-у и выберем имена людей, соответствующие записям для которых значения rentorsale в таблицах REAL_ESTATE и PEOPLE различаются.

 

SELECT name FROM PEOPLE, REAL_ESTATE WHERE REAL_ESTATE.rentorsale != PEOPLE.rentorsale;

+———-+
| name |
+———-+
| Alexandr |
| Katerina |
| Viktor |
| Boris |
| Olga |
| Nikolay |
| Sergey |
+———-+
7 rows in set (0.00 sec)

 

 

 

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

От дублирования результатов SELECT запросов можно избавиться добавляя ключевое слово DISTINCT

 

 

SELECT name FROM PEOPLE, REAL_ESTATE WHERE REAL_ESTATE.rentorsale = PEOPLE.rentorsale;

В выводе длинный список имен, всего 84 результата. Большая часть из них — дубли.

 

Убедимся в этом добавив DISTINCT

 

SELECT distinct name FROM PEOPLE, REAL_ESTATE WHERE REAL_ESTATE.rentorsale = PEOPLE.rentorsale;

+———-+
| name |
+———-+
| Alexandr |
| Katerina |
| Viktor |
| Boris |
| Olga |
| Nikolay |
| Sergey |
+———-+
7 rows in set (0.00 sec)

 

 

С JOIN-ами могут соседствовать и другие условия — например, ограничения на записи из таблицы PEOPLE в виде условия PRICE > 20000

 

SELECT distinct name FROM PEOPLE, REAL_ESTATE WHERE REAL_ESTATE.rentorsale = PEOPLE.rentorsale and PEOPLE.PRICE > 20000;

+———-+
| name |
+———-+
| Alexandr |
| Viktor |
| Olga |
| Nikolay |
+———-+
4 rows in set (0.00 sec)

 

Однако, возможно возникновение ошибок. Если вместо имен выводить районы города (в которых находятся квартиры и в которых квартиры желают снять или купить) — значения поля district возникнет неоднозначность

SELECT district FROM PEOPLE, REAL_ESTATE WHERE REAL_ESTATE.rentorsale = PEOPLE.rentorsale and PEOPLE.PRICE > 20000;

ERROR 1052 (23000): Column 'district' in field list is ambiguous

 

Причина в том, что поле district есть в обеих таблицах и MySQL не знает какие значения выводить.

 

Исправить ситуацию можно только непосредственно задав имя таблицы

SELECT PEOPLE.district FROM PEOPLE, REAL_ESTATE WHERE REAL_ESTATE.rentorsale = PEOPLE.rentorsale and PEOPLE.PRICE > 20000;

Такой запрос вернет 28 результатов

 

SELECT запросы можно усложнять и добавлять новые условия, JOIN-ов в условии WHERE может быть больше одного

 

SELECT PEOPLE.district FROM PEOPLE, REAL_ESTATE WHERE REAL_ESTATE.rentorsale = PEOPLE.rentorsale and PEOPLE.PRICE > 20000 and REAL_ESTATE.district = PEOPLE.district;

+————+
| district |
+————+
| Center |
| Center |
| Center |
| Center |
| Center |
| Center |
| Primorskiy |
| Center |
| Center |
| Center |
+————+
10 rows in set (0.00 sec)