Mysql запрос из нескольких таблиц

Mysql запрос из нескольких таблиц

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 основан на мультисетах, что означает дубликаты.

Читайте также:  Matlab построить график функции
От дублирования результатов 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)

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

Читайте также:  Bluestacks не запускается игра

Когда мы с Вами делали выборку из одной таблицы, то всё было очень просто:

SELECT названия_нужных_полей FROM название_таблицы WHERE условие_выборки

Всё очень просто и тривиально, но при выборке сразу из нескольких таблиц становится всё несколько сложнее. Одна из трудностей — это совпадение имён полей. Например, в каждой таблице есть поле id.

Давайте рассмотрим такой запрос:

SELECT * FROM table_1, table_2 WHERE table_1.id > table_2.user_id

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

Перед тем как читать дальше, попробуйте самостоятельно сообразить, как будет работать подобный SQL-запрос. Что он должен вывести?

Алгоритм работы следующий: берётся первая запись из table_1. Берётся id этой записи из table_1. Дальше полностью смотрится таблица table_2. И добавляются все записи, где значение поля user_id меньше id выбранной записи в table_1. Таким образом, после первой итерации может появиться от 0 до бесконечного количества результирующих записей. На следующей итерации берётся следующая запись таблицы table_1. Снова просматривается вся таблица table_2, и вновь срабатывает условие выборки table_1.id > table_2.user_id. Все записи, удовлетворившие этому условию, добавляются в результат. На выходе может получиться огромное количество записей, во много раз превышающих суммарный размер обеих таблиц.

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

Предыдущий SQL-запрос, как таковой, редко используется. Он был просто дан для объяснения алгоритма выборки из нескольких таблиц. А теперь же разберём более приземистый SQL-запрос. Допустим, у нас есть две таблицы: с товарами (есть поле owner_id, отвечающего за id владельца товара) и с пользователями (есть поле id). Мы хотим одним SQL-запросом получить все записи, причём чтобы в каждой была информация о пользователе и его одном товаре. В следующей записи была информация о том же пользователе и следущем его товаре. Когда товары этого пользователя кончатся, то переходить к следующему пользователю. Таким образом, мы должны соединить две таблицы и получить результат, в котором каждая запись содержит информацию о пользователе и об одном его товаре.

Читайте также:  Easy rsa build ca

Подобный запрос заменит 2 SQL-запроса: на выборку отдельно из таблицы с товарами и из таблицы с пользователями. Вдобавок, такой запрос сразу поставит в соответствие пользователя и его товар.

Сам же запрос очень простой (если Вы поняли предыдущий):

SELECT * FROM users, products WHERE users. >

Алгоритм здесь уже несложный: берётся первая запись из таблицы users. Далее берётся её id и анализируются все записи из таблицы products, добавляя в результат те, у которых owner_id равен id из таблицы users. Таким образом, на первой итерации собираются все товары у первого пользователя. На второй итерации собираются все товары у второго пользователя и так далее.

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

Есть две таблицы:
games (id, name, image) таблица с играми
uploaded_games (id, user_id, game_id) таблица с играми, которые загрузил пользователь с user_id

Нужно выбрать из таблицы games только те игры, которых нет в таблице uploaded_games.

Делал так:
SELECT * FROM games
LEFT JOIN uploaded_games
ON games. >
Запрос не работает (пустой запрос), пните в нужную сторону, пожалуйста.

Ссылка на основную публикацию
Adblock detector