Руководство по SQL. LEFT JOIN.

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

Запрос с использованием LEFT JOIN имеет следующий вид:

SELECT таблица1.колонка1, таблица2.колонка2...
FROM таблица1
LEFT JOIN таблицы2
ON таблицы1.общее_поле = таблица2.общее_поле;

Пример:

Предположим, что у нас есть две таблицы:
developers:

+----+-------------------+------------+------------+--------+
| ID | NAME              | SPECIALTY  | EXPERIENCE | SALARY |
+----+-------------------+------------+------------+--------+
|  1 | Eugene Suleimanov | Java       |          2 |   2500 |
|  2 | Peter Romanenko   | Java       |          3 |   3500 |
|  3 | Andrei Komarov    | JavaScript |          3 |   2500 |
|  4 | Konstantin Geiko  | C#         |          2 |   2000 |
|  5 | Asya Suleimanova  | UI/UX      |          2 |   1800 |
|  6 | Kolya Nikolaev    | Javascript |          5 |   3400 |
|  7 | Ivan Ivanov       | C#         |          1 |    900 |
|  8 | Ludmila Geiko     | UI/UX      |          2 |   1800 |
+----+-------------------+------------+------------+--------+

tasks:

+---------+-------------+------------------+------------+--------------+
| TASK_ID | TASK_NAME   | DESCRIPTION      | DEADLINE   | DEVELOPER_ID |
+---------+-------------+------------------+------------+--------------+
|       1 | Bug#123     | Fix company list | 2016-06-03 |            1 |
|       2 | Bug#321     | Fix registration | 2016-06-06 |            2 |
|       3 | Feature#777 | Latest actions   | 2016-06-25 |            3 |
+---------+-------------+------------------+------------+--------------+

Попробуем выполнить следующий запрос:

mysql> SELECT ID, NAME, TASK_NAME, DEADLINE 
FROM developers 
LEFT JOIN tasks 
ON developers. ID = tasks.DEVELOPER_ID;

В результате мы получим следующую таблицу:

+----+-------------------+-------------+------------+
| ID | NAME              | TASK_NAME   | DEADLINE   |
+----+-------------------+-------------+------------+
|  1 | Eugene Suleimanov | Bug#123     | 2016-06-03 |
|  2 | Peter Romanenko   | Bug#321     | 2016-06-06 |
|  3 | Andrei Komarov    | Feature#777 | 2016-06-25 |
|  4 | Konstantin Geiko  | NULL        | NULL       |
|  5 | Asya Suleimanova  | NULL        | NULL       |
|  6 | Kolya Nikolaev    | NULL        | NULL       |
|  7 | Ivan Ivanov       | NULL        | NULL       |
|  8 | Ludmila Geiko     | NULL        | NULL       |
+----+-------------------+-------------+------------+

Как мы видим, мы получили все записи из таблицы developers, а поля второй таблицы для записей, у которых нет совпадений в таблице tasks, имеют значение NULL.

На этом мы заканчиваем изучение LEFT JOIN.

SQL OUTER JOIN — левое соединение, правое соединение и полное внешнее соединение

Если вы хотите узнать о SQL INNER JOIN, ознакомьтесь с руководством по SQL INNER JOIN.

Существует три вида ВНЕШНИХ СОЕДИНЕНИЙ: левое внешнее соединение, правое внешнее соединение и полное внешнее соединение. Рассмотрим каждый вид соединения более подробно.

SQL OUTER JOIN — левое внешнее соединение

Левое внешнее соединение SQL также известно как левое соединение SQL. Предположим, мы хотим соединить две таблицы: A и B. Левое внешнее соединение SQL возвращает все строки в левой таблице (A) и все совпадающие строки, найденные в правой таблице (B). Это означает, что результат левого соединения SQL всегда содержит строки в левой таблице.

Ниже показан внешний синтаксис SQL для объединения двух таблиц: table_A и table_B:

   SELECT column1, column2...
ИЗ таблицы_A
LEFT JOIN table_B ON join_condition
ГДЕ row_condition  

SQL OUTER JOIN — пример левого внешнего соединения

Следующий запрос выбирает всех клиентов и их заказы:

   SELECT c.customerid,
       c.companyName,
       номер заказа
ОТ клиентов c
LEFT JOIN заказы o ON o.
customerid = c.customerid ORDER BY orderid

Перечислены все строки в таблице клиентов . В случае, если в таблице заказов нет соответствующей строки для строки в клиентов , столбец orderid в таблице заказов заполняется значениями NULL.

Мы можем использовать диаграмму Венна, чтобы визуализировать, как работает SQL LEFT OUTER JOIN.

ВНЕШНЕЕ СОЕДИНЕНИЕ SQL — правое внешнее соединение

Правое внешнее соединение SQL возвращает все строки в правой таблице и все соответствующие строки, найденные в левой таблице. Синтаксис правого внешнего соединения SQL следующий:

   SELECT столбец1, столбец2...
ИЗ таблицы_A
ПРАВОЕ СОЕДИНЕНИЕ table_B ON join_condition
ГДЕ row_condition 

Правое внешнее соединение SQL также известно как правое соединение SQL.

SQL OUTER JOIN – пример правого внешнего соединения

Следующий пример демонстрирует правое внешнее соединение SQL:

   SELECT c. customerid,
       c.companyName,
       номер заказа
ОТ клиентов c
Заказы RIGHT JOIN o ON o.customerid = c.customerid
ORDER BY orderid  

Запрос возвращает все строки в таблице заказов и все совпадающие строки, найденные в клиентов стол.

На следующей диаграмме Венна показано, как работает правое внешнее соединение SQL:

SQL OUTER JOIN — полное внешнее соединение

Синтаксис полного внешнего соединения SQL следующий:

   SELECT column1, column2...
ИЗ таблицы_A
ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ table_B ON join_condition
WHERE row_condition  

Полное внешнее соединение SQL возвращает:

  • все строки в левой таблице table_A.
  • все строки в правой таблице table_B.
  • и все соответствующие строки в обеих таблицах.

Некоторые системы управления базами данных не поддерживают синтаксис полного внешнего соединения SQL, например, MySQL. Поскольку полное внешнее соединение SQL возвращает результирующий набор, который является комбинированным результатом левого и правого соединения SQL.

Поэтому вы можете легко эмулировать полное внешнее соединение SQL, используя левое соединение SQL и правое соединение SQL с оператором UNION, следующим образом:

   SELECT столбец1, столбец2...
ИЗ таблицы_A
LEFT JOIN table_B ON join_condition
СОЮЗ
ВЫБЕРИТЕ столбец1, столбец2...
ИЗ таблицы_A
ПРАВОЕ СОЕДИНЕНИЕ table_B ON join_condition  

SQL OUTER JOIN – пример полного внешнего соединения

Следующий запрос демонстрирует полное внешнее соединение SQL:

 SELECT c.customerid,
       c.companyName,
       номер заказа
ОТ клиентов c
Заказы FULL OUTER JOIN o ON o.customerid = c.customerid
ORDER BY orderid 

На следующей диаграмме Венна показано, как работает полное внешнее соединение SQL:

В этом руководстве вы узнали о различных ВНЕШНИХ СОЕДИНЕНИЯХ SQL, включая левое соединение SQL, правое соединение SQL и полное внешнее соединение SQL.

sql — левое соединение с пунктом «Где»

Задавать вопрос

спросил

Изменено 1 год, 2 месяца назад

Просмотрено 573k раз

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

Но этот запрос извлекает только те настройки, где символ = 1, а не настройки по умолчанию, если пользователь ничего не настроил.

 ВЫБЕРИТЕ `настройки`.*, `character_settings`.`значение`
ОТ (`настройки`)
LEFT JOIN `character_settings`
ON `character_settings`.`setting_id` = `settings`.`id`
ГДЕ `character_settings`.`character_id` = '1'
 

Итак, мне нужно что-то вроде этого: массив

(
    '0' => массив('somekey' => 'имя ключа', 'значение' => 'значение'),
    '1' => массив('somekey2' => 'keyname2'),
    '2' => массив('somekey3' => 'keyname3')
)
 

Где ключ 1 и 2 являются значениями по умолчанию, когда ключ 0 содержит значение по умолчанию с символьным значением.

  • sql
  • левое соединение
  • где-пункт
0

Предложение where отфильтровывает строки, в которых левое соединение не удается. Переместите его в соединение:

 SELECT `settings`.
*, `character_settings`.`value` ИЗ `настроек` ЛЕВОЕ СОЕДИНЕНИЕ `настройки персонажа` ON `character_settings`.`setting_id` = `settings`.`id` И `character_settings`.`character_id` = '1'
1

При выполнении ВНЕШНИХ СОЕДИНЕНИЙ (ANSI-89 или ANSI-92) место фильтрации имеет значение, поскольку критерии, указанные в пункте ON , применяются до выполнения СОЕДИНЕНИЯ . Критерии для таблицы OUTER JOINed, представленные в предложении WHERE , применяются после выполнения JOIN . Это может привести к очень разным наборам результатов. Для сравнения, для ВНУТРЕННИХ СОЕДИНЕНИЙ не имеет значения, указаны ли критерии в

ON или WHERE — результат будет тот же.

 ВЫБРАТЬ с.*,
          cs.`значение`
     ИЗ НАСТРОЕК
LEFT JOIN CHARACTER_SETTINGS cs ON cs.setting_id = s.id
                               И cs.character_id = 1
 
0

Если я правильно понимаю ваш вопрос, вам нужны записи из базы данных настроек, если они не имеют соединения с таблицей character_settings или если эта объединенная запись имеет character_id = 1.

Поэтому вы должны сделать

 SELECT `settings`.*, `character_settings`.`value`
ОТ (`настройки`)
ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ `character_settings`
ON `character_settings`.`setting_id` = `settings`.`id`
ГДЕ `character_settings`.`character_id` = '1' ИЛИ
`character_settings`.character_id равен NULL
 
2

Вам может быть проще понять, используя простой подзапрос

 SELECT `settings`.*, (
    ВЫБЕРИТЕ `значение` ИЗ `character_settings`
    ГДЕ `character_settings`.`setting_id` = `настройки`.`id`
      И `character_settings`.`character_id` = '1') AS cv_value
ИЗ `настроек`
 

Подзапрос может возвращать null, поэтому вам не нужно беспокоиться о JOIN/WHERE в основном запросе.

Иногда это работает на быстрее в MySQL, но сравните его с формой LEFT JOIN, чтобы увидеть, что лучше всего подходит для вас.

 ВЫБРАТЬ с.*, c.значение
ИЗ настроек с
LEFT JOIN character_settings c ON c.setting_id = s.id AND c. character_id = '1'
 

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

 с settings_for_char как (
  выберите setting_id, значение из character_settings, где character_id = 1
)
выбирать
  настройки.*,
  settings_for_char.value
от
  настройки
  оставил соединение settings_for_char на settings_for_char.setting_id = settings.id;
 

То, как я, наконец, понимаю, верхний ответ заключается в том, что осознается (следуя порядку выполнения SQL-запроса), что предложение WHERE применяется к объединенной таблице , тем самым отфильтровывая строки, которые не удовлетворяют условию WHERE из объединенного ( или вывод) таблица. Однако перемещение условия WHERE в предложение ON применяет его к отдельным таблицам 9.0003 до присоединения к .