Объяснение SQL объединений JOIN/INNER/OUTER

Категория: / Mine блог / PHP (LAMP)
Имеем две таблицы

 
U) users               D) departments
id name       d_id     id  name
-- ----       ----     --  ----
1  Владимир    1       1  Сейлз
2  Антон       2       2  Поддержка
3  Александр   6       3  Финансы
4  Борис       2       4  Логистика
5  Юрий        4
 


 
SELECT u.id, u.name, d.name AS d_name
FROM users u
INNER JOIN departments d ON u.d_id = d.id
 


Запрос вернет объединенные данные, которые пересекаются по условию, указанному в INNER JOIN. В результате не присутствует:
- пользователь Александр (отдел 6)
- отдел Финансы (нет пользователей)

 
id name       d_name
-- --------   ---------
1  Владимир    Сейлз
2  Антон       Поддержка
4  Борис       Поддержка
3  Юрий        Логистика
 


sql inner join

рис. Inner join

INNER JOIN это синоним для JOIN. Выбираются только совпадающие данные из объединяемых таблиц. Чтобы получить данные, которые не подходят по условию, необходимо использовать OUTER JOIN. Такое объединение вернет данные из обеих таблиц совпадающими по одному из условий.

sql left join

рис. Left join

Существует два типа внешнего объединения (OUTER JOIN) - LEFT OUTER JOIN и RIGHT OUTER JOIN. Работают они одинаково, разница заключается в том что LEFT - указывает что "внешней" таблицей будет находящаяся слева. В нашем примере это таблица users.

 
SELECT u.id, u.name, d.name AS d_name
FROM users u
LEFT OUTER JOIN departments d ON u.d_id = d.id
 


Получаем полный список пользователей и сопоставленные департаменты.

 
id      name          d_name
--      --------      ---------
1       Владимир      Сейлз
2       Антон         Поддержка
3       Александр     NULL
4       Борис         Поддержка
5       Юрий          Логистика
 


sql left outer join

рис. Left outer join с фильтрацией по полю

RIGHT OUTER JOIN вернет полный список департаментов (правая таблица) и сопоставленных пользователей.

 
SELECT u.id, u.name, d.name AS d_name
FROM users u
RIGHT OUTER JOIN departments d ON u.d_id = d.id
WHERE u.id IS NULL
 


 
id      name        d_name
--      --------    ---------
1       Владимир    Сейлз
2       Антон       Поддержка
4       Борис       Поддержка
NULL    NULL        Финансы
5       Юрий        Логистика
 


Дополнительно можно отфильтровать данные, проверяя их на NULL.
В нашем примере указав WHERE u.id IS null, мы отбросим записи, в которых пользователи не числятся в отделах.

Информация:
http://www.somecoders.com/2006/02/explanation-of-the-different-sql-joins/
http://www.khankennels.com/blog/index.php/archives/2007/04/20/getting-joins/
http://www.codinghorror.com/blog/archives/000976.html


Self joins

Так называемая выборка с замыканием на себя (и совсем не closure). Нужна нам, если необходимо выбрать более одного
значения из таблицы для нескольких условий.

Имеем: набор фильтров для информации, значения которых сохраняются в табличке filts_data.
Необходимо: фильтровать продукты по дате, артикулу и имеющимся фильтрам

 
CREATE TABLE filts_data
(
  id serial NOT NULL,
  fid integer NOT NULL-- product_item.id
  value integer NOT NULL, -- значение фильтра filts_items.id
  pid integer NOT NULL -- фильтр filts.id
)
 


Есть таблица условных товаров product_item

 
CREATE TABLE product_item
(
  id serial NOT NULL,
  section_id integer,
  date timestamp,
  art text,
  title text
)
 


Пример: выбрать записи, добавленные после 17/01/2009 и с установленными фильтрами 3=14 и 4=15 и 6=19.
Логика подскажет нам такой запрос (нерабочий):

SELECT p1.title FROM products_item p1 INNER JOIN filts_data p2 ON p1.id = p2.fid
WHERE p1.date > '17.01.2009' AND (p2.pid = 3 AND p2.value = 14) AND (p2.pid = 4 AND p2.value = 15) AND (p2.pid = 6 AND p2.value = 19)


Этот запрос не найдет элементов в таблице.
Перепишем запрос, используя join на себя:

SELECT p1.* FROM product_item p1 INNER JOIN filts_data p2 ON p1.id = p2.fid  INNER JOIN filts_data p3 ON p1.id = p3.fid  INNER JOIN filts_data p4 ON p1.id = p4.fid WHERE p1.date > '17.01.2009' AND (p2.pid = 3 AND p2.value = 14) AND (p3.pid = 4 AND p3.value = 15) AND (p4.pid = 6 AND p4.value = 19)


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

@author: surg30n
@date: Пятница, 14 Март 2008


Комментарии : 34


34] Гость - 19:00, 02 Ноябрь, 2011
Кратко и понятно, спасибо
33] Гость - 16:08, 17 Апрель, 2011
Неебически выручили, спасибо за последний пример!!
32] Гость - 12:58, 21 Февраль, 2011
Спасибо!
Готовлюсь к собеседованию, статья помогла :)
31] Гость - 22:25, 10 Февраль, 2011
Спасибо. Толковая статья в максимально понятном объяснении. Ставлю 5+
30] Гость - 08:32, 30 Август, 2010
Большое спасибо, полезная статья!
29] Гость - 09:36, 25 Август, 2010
все хорошо, но уберите боковое меню. Мало того, что оно мешает, так оно еще и не функционально!
28] Гость - 07:03, 03 Август, 2010
Спасибо! Очень понравилась статья, доступно и понятно описано.
27] Гость - 09:21, 20 Июль, 2010
Помогите вот с чем, имею 2 таблицы:
U) users
id name
1 Владимир
2 Антон
3 Александр
4 Борис
5 Юрий

D) вщдп
id d_id name
1 1 100
1 2 200
1 3 100
2 1 200
2 2 100
3 1 200
3 2 100
3 3 200
3 4 100

Нужен запрос вывода всех сотрудников и вывод сумм по d.id
В итоге иметь вот это (запрос d.id=2)

Владимир 200
Антон 100
Александр NULL
Борис NULL
Юрий NULL

26] Гость - 13:33, 12 Июль, 2010
Статья хорошая - коротко и ясно написано.
Только вот тут неточность имеется: "В нашем примере указав WHERE u.id IS null, мы отбросим записи, в которых пользователи не числятся в отделах."
кроется неточность. Вернее будет так:
"В нашем примере указав WHERE u.id IS NOT null, мы отбросим записи, в которых пользователи не числятся в отделах."
или так:
"В нашем примере указав WHERE u.id IS null, мы получим отделы, в которых не числятся пользователи."
25] Гость - 22:17, 30 Май, 2010
спасибо большое!!! самое толковое объяснение, которое нашла в инете. в смысле самое доступное и наглядное.
24] Гость - 20:02, 23 Май, 2010
Нормалек
<script>alert(312)</script>
23] Гость - 01:00, 28 Март, 2010
thank _you_ and_regards
22] Гость - 14:47, 21 Январь, 2010
Объясните, пожалуйста если в одном запросе есть и inner и left join, что будет в результате?
21] Гость - 11:48, 08 Сентябрь, 2009
>> выбрать записи старее 17/01/2009

>> p1.date > '17.01.2009'
>> и дата больше заданной

???
20] Гость - 16:00, 27 Август, 2009
точно - полный бред
19] Гость - 09:08, 21 Август, 2009
Отлично написано! Спасибо!
18] Гость - 13:46, 13 Август, 2009
Очень помоглю. Спасибо.
17] Гость - 17:45, 17 Июль, 2009
left outer join... че за хрень здесь написана?
16] j4ck - 18:25, 14 Июль, 2009
>> 15] Гость

Ваш запрос вернет выборку, в которой задействован один из фильтров, а необходимым условием является выборка со всеми параметрами фильтра.
15] Гость - 12:40, 14 Июль, 2009
SELECT p1.title FROM products_item p1 INNER JOIN filts_data p2 ON p1.id = p2.fid
WHERE p1.date > '17.01.2009' AND (p2.pid = 3 AND p2.value = 14) AND (p2.pid = 4 AND p2.value = 15) AND (p2.pid = 6 AND p2.value = 19)

А сделать так?
SELECT p1.title FROM products_item p1 INNER JOIN filts_data p2 ON p1.id = p2.fid
WHERE p1.date > '17.01.2009' AND ((p2.pid = 3 AND p2.value = 14) OR (p2.pid = 4 AND p2.value = 15) OR (p2.pid = 6 AND p2.value = 19))
14] Гость - 12:07, 23 Июнь, 2009
Супер! Отлично рассказано!
13] Гость - 12:51, 09 Июнь, 2009
поправьте:
left join = left outer join
right join = right outer join
картинка для left join правильная, для left outer join неправильная
12] Гость - 12:22, 09 Июнь, 2009
спасибо, очень здорово написано
а то голова уже болела от этих joinов
11] Гость - 09:55, 19 Май, 2009
Бред блин написан!!!!!!!!!!!!!
10] Гость - 10:13, 14 Май, 2009
спасибки
9] Гость - 15:49, 12 Май, 2009
Везде бы так поясняли
8] Гость - 14:43, 21 Апрель, 2009
Вспомнил что хотел. Спасибо, помогло.
7] Гость - 11:22, 08 Апрель, 2009
Отличная статья, очень помогла!
6] Гость - 16:33, 30 Март, 2009
Бред сивой кобылы в части описания OUTER JOIN.
Особенно порадовала фраза "Такое объединение вернет все данные из обоих таблиц."
И картинки у вас знатные.

Авторы, хорошая трава была, а ?

5] Гость - 03:43, 25 Февраль, 2009
Чиорт!:)

ПомоглО:)
4] Гость - 03:43, 25 Февраль, 2009
Очень помогла. Большое спасибо.
3] Гость - 17:07, 12 Февраль, 2009
Блестяще, спасибо.
2] Гость - 22:22, 31 Январь, 2009
гарна стаття тільки про OUTER JOIN мало сказано!!!!
1] Гость - 20:36, 02 Октябрь, 2008
отлично!
Комментировать:




Код подтверждения: *
Введите подтверждающий код, так же как он отображен на картинке.
Надоело разбирать числа на картинке? Зарегистрируся, докажи что ты не робот!

загрузка...

Интернет магазин: готовый интернет магазин. Сделать Интернет-магазин. . Новое объявление про пылесос без мешка для сбора пыли. Купить пылесос без мешка. . Пейнтбол магазин ослепительно. Другое пейнтбол магазин.