January
2006
Операторы Inner Join и Outer (left, right, full) Join в SQL (Oracle)
Posted in: Базы данных, SQL, Oracle |
Ключевое слово join в SQL используется при построении select выражений. ?нструкция Join позволяет объединить колонки из нескольких таблиц в одну. Объединение происходит временное и целостность таблиц не нару?ается. Существует три типа join-выражений:
- inner join;
- outer join;
- cross join;
В свою очередь, outer join может быть left, right и full (слово outer обычно опускается).
В качестве примера (DBMS Oracle) создадим две простые таблицы и сконструируем для них SQL-выражения с использованием join.
В первой таблице будет хранится ID пользователя и его nick-name, а во второй - ID ресурса, имя ресурса и ID пользователя, который может этот ресурс администрировать.
create table t_users ( t_id number(11, 0), t_nick varchar(16), primary key (t_id) ) create table t_resources ( t_id number(11, 0), t_name varchar(16), t_userid number (11, 0), primary key (t_id) )
Содержимое таблиц пусть будет таким:
T_ID T_NICK 1 user1 3 user3 4 user4 T_ID T_NAME T_USERID 1 res1 3 2 res2 1 3 res3 2 5 res5 3
Конструкция join выглядит так:
... join_type join table_name on condition …
Где join_type - тип join-выражения, table_name - имя таблицы, которая присоединяется к результату, condition - условие объединения таблиц.
Кострукция join располагается сразу после select-выражения. Можно использовать несколько таких конструкций подряд для объединения соответствующего кол-ва таблиц. Логичнее всего использовать join в том случае, когда таблица имеет вне?ний ключ (foreign key).
Inner join необходим для получения только тех строк, для которых существует соответствие записей главной таблицы и присоединяемой. ?ными словами условие condition должно выполняться всегда. Пример:
select t_resources.t_name, t_users.t_nick from t_resources inner join t_users on t_users.t_id = t_resources.t_userid
Результат будет таким:
T_NAME T_NICK res2 user1 res1 user3 res5 user3
В случае с left join из главной таблицы будут выбраны все записи, даже если в присоединяемой таблице нет совпадений, то есть условие condition не учитывает присоединяемую (правую) таблицу. Пример:
select t_resources.t_name, t_users.t_nick from t_resources left join t_users on t_users.t_id = t_resources.t_userid
Результат выполнения запроса:
T_NAME T_NICK res1 user3 res2 user1 res3 (null) res5 user3
Результат показывает все ресурсы и их администраторов, вне зависимотсти от того есть они или нет.
Right join отображает все строки удовлетворяющие правой части условия condition, даже если они не имеют соответствия в главной (левой) таблице:
select t_resources.t_name, t_users.t_nick from t_resources right join t_users on t_users.t_id = t_resources.t_userid
А результат будет следующим:
T_NAME T_NICK res2 user1 res1 user3 res5 user3 (null) user4
Результирующая таблица показывает ресурсы и их администраторов. Если адмнистратор не задействован, эта запись тоже будет отображена. Такое может случиться, например, если ресурс был удален.
Updated (8.03.2007):
Full outer join (ключевое слово outer можно опустить) необходим для отображения всех возможных комбинаций строк из нескольких таблиц. ?ными словами, это объединение результатов left и right join.
select t_resources.t_name, t_users.t_nick from t_resources full join t_users on t_users.t_id = t_resources.t_userid
А результат будет таким:
T_NAME T_NICK res1 user3 res2 user1 res3 (null) res5 user3 (null) user4
Некоторые СУБД не поддерживают такую функциональность (например, MySQL), в таких случаях обычно используют объединение двух запросов:
select t_resources.t_name, t_users.t_nick from t_resources left join t_users on t_users.t_id = t_resources.t_userid union select t_resources.t_name, t_users.t_nick from t_resources right join t_users on t_users.t_id = t_resources.t_userid
Наконец, cross join. Этот тип join еще называют декартовым произведением (на английском - cartesian product). Настоятельно рекомендую использовать его с умом, так как время выполнения запроса с увеличением числа таблиц и строк в них растет по экспоненте.
Вот пример запроса, который аналогичен cross join:
select t_resources.t_name, t_users.t_nick from t_resources, t_users
Конструкция Join (в сочетании с другими SQL конструкциями, например, group by) часто встречается при программировании под базы данных. Думаю, эта статья будет вам полезна. Кстати, для проверки своих знаний в области баз данных (и в частности Oracle) рекомендую воспользоваться этим сайтом онлайн тестирования - Тесты по базам данных.
98 Comments »
RSS feed for comments on this post. TrackBack URI
думаю будет полезна.. но мало рассказано.. так всё быстро… а вот как написать запрос, что бы выводились те записи с первой таблицы. которых нет во второй?
это тоже следует написать
В статье описано, как и для чего можно использовать конструкцию join. Естественно, для определенных задач и для сложных баз данных запросы будут сложнее: со вложенными запросами, с конструкциями where, group by, c ключевыми сдовами типа distinct и так далее…
Как раз то, что нужно - сейчас 3 часа ночи и вот появилось легкое непонимание разниц INNER и LEFT/
(Тут еще OUTER JOINT проскакивает - буду разбираться еще).
Вы помогли _быстро_ разобраться
Спасибо!
Отлично! Как в хоро?ем справочнике: коротко и ясно. Спасибо!
Очень хоро?ая статья. Все четко и понятно. Молодцы.
Хоро?ая статья, помогла. Кратко и ясно. То, что нужно было для начала ;).
Понятно но сли?ком уж кратко. Хотя бы ссылку на более подробную статью чтоли. Но все равно спасибо. Главное дано сравнение всех JOIN. Но не понятно что делать если объединяется одна и та же таблица под разными именами
Статья действительно хоро?а. Спасибо.
Огромное спасибо, отличная статья. Моментально стало всё ясно.
? я благодарность наверное выпи?у за статейку ![]()
Спасибо. Как раз по лабе, которую щас буду делать ![]()
Хоро?ая статья. Мне на собеседовании вопрос про outer join задавали, а я толком ничего сказать не смог. Теперь вроде бы все ясно, спасибо!
Да статья действительно получилось хоро?ая. Она не вдаваясь в детали объясняет суть! А за подробностями можно не полениться и залезть в мануал СУБД
Ещё стоило бы упомянуть, что в Oracle, по крайней мере в 9i, есть определённые проблемы с ANSI-?ным синтаксисом join-ов. Хотя в документации и советуется его использовать взамен оракловых (+).
Поэтому пользоваться ANSI-синтаксисом следует с осторожностью (особенно full).
Подробности можно посмотреть на Металинке.
Хоро?ая статейка, мне понравилось. Коротко, ясно, а главное доступно… Без засирания мозга полным синтакиссом опреаторов и прочего. Очень наглядно продемонстрировано. Сам работаю с MySQL, однако было очень интересно прочитать. Спасибо.
Всё хоро?о, корме одного:
В Oracle нет операции JOIN. Вне?ние соединения обеспечиваются в Oracle оператором (+) в эквисоединении.
Хоро?ая статья. Спасибо за простое изложение информации.
Неплохо было бы добавить чуть-чуть инфы о том когда следует пользоваться join.
Боль?ое спасибо, инфа полезная! Как раз сдавать лабы по бд!
Боль?ое спасибо за такую понятную статью. очень доступно всё описано.
А что делает такой select:
Select …
from table1 left join table2 right join table3
on (join condition table2 - table3)
on (join condition table1 - table2)
Какие колонки должны попасть в результат?
? мне статья понравилась: просто и понятно. Спасибо
Great Thanks to you!
From Ubonratchathani University
will try to explain it to the students!
Спасибо, коротко и доступно о нужном )
Боль?ое спасибо, очень полезная стать!
Класс….. +1
>>>а вот как написать запрос, что бы выводились те записи с первой таблицы. которых нет во второй?
select t_resources.t_name, t_users.t_nick
from t_resources
left join t_users
where t_users.t_nick is null
![]()
а я рань?е работала с mssql, на новой работе оракл, и почему-то запросы с джоинами не выполняются, даже простей?ие, типа select t1.p1,t2.p2 from t1 left join t2 on t1.p1=t2.p2 не могу понять, в оракле другой синтаксис или вообще нет оператора join?:(
всем спасибо, я уже на?ла)))) это будет так:
select t1.p1,t2.p2 from t1, t2 where t1.p1=t2.p2 (+) = left join
select t1.p1,t2.p2 from t1, t2 where t1.p1(+)=t2.p2 = right join
Очень неплохая статья.
Спасибки, статейка полезная ))
мда, я ничего не имею против деву?ек it, но я хотел узнать, как правильно искользовать джойны, и заглянул сюда. Первый же пример вызвал у меня сомнения… Создал все в точности в оракловой базе, и в певом запросе выдет 4 записи, а не 3, как показано тут. Следовательно объяснения про inner join уже не верны, даль?е читать расхотелось…
Может мы о разных Ораклах говорим?
Спасибо! самая суть…четко , коротко и понятно!!
Спасибо, я наконец поняла как полозоваться джоином :)))
Целый день “гуглил” инет, искал “а вот как написать запрос, что бы выводились те записи с первой таблицы. которых нет во второй?”, где-то к обеду узнал, что мне нужен JOIN и только к полуночи инет все таки раскрыл ТАЙНУ кто такой JOIN. Огромное спасибо ва?ей статье!!!
может, я не прав, но, на мой взгляд, луч?е использовать подзапросы. Они и нагляднее и проще пи?утся. А этими Джойнами можно себе мозг взорвать
2Дима:
То что проще, не обязательно быстрее.
Автору спасибо
Minus вместо Union выводит то из первой таблицы, чего нет во второй.
Мне вот интересно сравнить скорость двух запросов возвращающих одинаковые данные но использующие inner join и left join
?
?нтересно-сравни.
в оракле поддержка join-ов появилась с 9-й версии, если мне память не изменяет.
LexSTV - ты видимо что-то не так делал. Я создал таблицы в точности с приведенными примерами, проверил все опубликованные запросы в MySQL, и убедился в их правильности - все результаты абсолютно сообтветствовали с опубликованными примерами.
Возможно Oracle интерпритирует данные запросы по другим правилам, в результате чего результат отличаеться, но скорее всего ты НЕ буквально воссоздал картину, показанную на примере вы?е. Поэтому “захоти” и почитай статью внимательнее, может что-то полезное для себя узнае?ь.
Автору спасибо!
Да, статейка действительно доходчивая - доза теории и двойная доза практики
Спасибо.
Классно
саое понятное из всех объяснений принципа работы JOIN, которое мне попадалось! Благодарю!
Оч хоро?ая статья!
Автору респект!
Ждем новых статей =)
Спасибо! Очень помогло!
Кратко и понятно!
“wert2all January 6, 2006 # … а вот как написать запрос, что бы выводились те записи с первой таблицы. которых нет во второй? это тоже следует написать”
For you:
select t_resources.t_name, t_users.t_nick
from t_resources
right join t_users on t_users.t_id = t_resources.t_userid
where t_resources.t_name is null
А результат будет следующим:
T_NAME T_NICK
(null) user4
Спасибо. Теперь стало понятнее, чем именно отличаются все эти LEFT, RIGHT JOIN и т.д.
спасибо, статья помогла все быстро выяснить
Отличная статья! Все четко и по сути!
———-
Наконец, cross join. Этот тип join еще называют декартовым произведением (на английском - cartesian product). Настоятельно рекомендую использовать его с умом, так как время выполнения запроса с увеличением числа таблиц и рядков в них растет по экспоненте.
———-
может стоит открыть учебник алгебры и изучить что такое экспонента?
Спасибо. Полезная статья.
спс!
LexSTV April 13, 2008 # мда, я ничего не имею против деву?ек it, но я хотел узнать, как правильно искользовать джойны, и заглянул сюда. Первый же пример вызвал у меня сомнения… Создал все в точности в оракловой базе, и в певом запросе выдет 4 записи, а не 3, как показано тут. Следовательно объяснения про inner join уже не верны, даль?е читать расхотелось…
Я думаю автор статьи - Константин - обидится за то, что его обозвали “деву?кой it”
а то, что ты первым делом обратил внимание на пол автора, говорит о том, что ты “ничего не имее?ь против деву?ек (it), но они все поголовно дуры”. Думаю, предвзятость идет из внутренних комплексов и проблем в личном общении
#может стоит открыть учебник алгебры и изучить что такое экспонента?
стоит. изучи.
Автору спасибо за статью!
jocker1331…тут уже тебе ре?ать, открывать алгебру или нет…
статья очень полезна, спасибо!!!
автору респект и уважуха
ЗАДАЧА
1. Таблица GROUP (содержит значения Группа1, Группа2, Группа3)
2. Таблица STUDENT (содержит значения Петров, ?ванов, Сидоров в привязке к Группе1)
3. Таблица BALL (содержит итоговый балл: по Петрову - 82, по ?ванову - 69, по Сидорову - NULL)
НАДО вывести Группу1, всех студентов этой группы и ?тоговый балл, даже если он еще не назначен.
РЕШЕН?Е:
SELECT group.name, student.name, ball.score
from ball
RIGHT JOIN (student RIGHT JOIN group ON group.id = student.id )
ON student.id = ball.id
WHERE group.name = ‘Группа1′
JOIN прикольная тема
а описано все как нужно. конкретно и без слюней ![]()
2 Sergey
В скобках надо использовать LEFT JOIN.
?наче будет работать неправильно, если для студента не будет указана группа (или будет указана группа, отсутствующая в таблице GROUP):
SELECT group.name, student.name, ball.score
from ball
RIGHT JOIN (student LEFT JOIN group ON group.id = student.id )
ON student.id = ball.id
WHERE group.name = ‘Группа1′
А кто знает, как сделать, чтобы вместо (null) в DataGrid выводился, например, пробел?
Отличная статья, спасибо!
Спасибо!
А не подскажите, каким способом эти таблицы тупо склеить в одну, при условии уникальности ID и совпадения названий полей чтобы делать выборку уже оттуда?
T_ID T_NICK
1 user1
3 user3
4 user4
6 res1
7 res2
8 res3
5 res5
SELECT `T_ID` FROM t_users+t_resources WHERE `T_NICK`=’res5′
??? Спасибо!
Хоро?ая статья… давно хотел разобраться с этими “джоинами” ![]()
Спасибо!
Спасибо, помогло быстро разобраться.
Честно говоря пытаясь на собственных таблицах создать select с join’ом сначала запутался, но потом разобрался почему:
потому что в самом начале статьи я бы переписал:
”
Конструкция join выглядит так:
… join_type join table_name on condition …”
на:
”
Конструкция join выглядит так:
…table1_name join_type join table2_name on condition …”
? вот уже отсюда, по-моему, чуть яснее, кто есть правая, а кто левая таблицы.
А вообще - спасибо за статью ![]()
полностью все 100% описано понятно и ясно сходу.
теория + примеры.
спс.
Нормальная статья, только слово “рядки” насме?ило сильно. Правильно “ряды”, конечно.
Спасибо за статью, ре?ил просто освежить знания и наткнулся на вас.
Немного запутано про левые и правые таблицы.
В целом все понятно. Спасибо.
2 ap: спасибо, исправил. Это я с украинским языком спутал
А кто знает, как сделать, чтобы вместо (null) в DataGrid выводился, например, пробел?
nvl(,)
выглядит так
select nvl(a.name,’нет имени’) from students a
Отличная статья! Спасибо очень быстро разобрался с Full Join. Как раз то что нужно было!
wert2all как раз LEFT JOIN и отвечает на Ва? вопрос: все записи с первой таблицы
не вижу смысла вообще использовать inner join
использую Oracle SQL 10 лет и мне удобнее
и нагляднее написать (особенно если много полей
в условии where)
select t_resources.t_name, t_users.t_nick
from t_resources, t_users
where t_users.t_id = t_resources.t_userid
чем
select t_resources.t_name, t_users.t_nick
from t_resources
inner join t_users on t_users.t_id = t_resources.t_userid
Спра?иваю у программиста на новой работе- почему ты используе?ь inner join вместо простого сравнения полей , отвечает меня так научили
Хоро?ая статья, вот только искал описание по NATURAL JOIN, я себе представляю как работает, но хотелось бы точно)
Пример:
SELECT E.employee_id, E.last_name, department_id, D.department_name
FROM employees E
NATURAL JOIN
departments D
WHERE department_id = 30;
Если я правильно понял, то идет пересение по ключам (priary и foreign key))
Спасибо, прекрасная статья.
Наконец то я понял, как работают разные Join … спасибо за краткое и понятное обьяснение
Работаю с PL/SQL-Developer уже боль?е пол-года, несколько раз пробовал понять этот join, и на этом примере токо уразумел (опробовал, все норм). Спасибо автору.
Статейка классная ибо автор воздержался блеснуть умом и доходчиво рассказал по сути!
Спасибо!
skAmZ,
natural join сочленяет по столбцам с одинаковыми именами (обычно по одному столбцу имена совпадают (в боль?инстве случаев там, где и хоче?ь сочленить), но могут несколько совпасть, тогда по ним сочленяется (ON(Т1.с1=Т2.c1)AND(Т1.с2=Т2.c2)) хотя корректней писать (ON(Т1.с1, Т1.с2)=(Т2.с1, Т2.с2)) )
также вместо ON Т1.с1=Т2.c1 можно писать USING(c1)
Отличная статья помогла разобраться с join. Спасибо !
2 Sergey
Спасибо! Ва? пост помог ре?ить мою задачу, используя вложенные join.
to Nuke:
А кто знает, как сделать, чтобы вместо (null) в DataGrid выводился, например, пробел?
COL[UMN]имя_столбца NULL “то, что хоче?ь
вставить вместо NULL”;
Удалить: CLEAR COLUMN
также:
SELECT tr.t_name, tu.t_nick
FROM t_resources tr
FULL OUTER JOIN t_users tu
ON tu.t_id = tr.t_userid;
Результат:
T_NAME T_NICK
res2 user1
res5 user3
res1 user3
res3
user4
Насчет FULLa - незаметил, sorry.
2Rustam:
Но не понятно что делать если объединяется одна и та же таблица под разными именами
SELECT p.t_name, g.t_name
FROM t_resources g, t_resources p
WHERE g.t_id = p.t_userid;
[…] » Операторы Inner Join и Outer left, right, full Join в SQL Oracle. […]
Четко, ясно и понятно. А то когда только начал изучать SQL про join было написано настолько муторно что просто махнул на них рукой, да и особой необходимости в них не было
спасиба!!
Как обьединить несколько left join в delphi?
Статья помогла написать
Ялтинский портал
Блин, спасибо, огромное. А то в поисковике голимые цитаты из официального мануала, где ужасно дуратские примеры
А так сразу всё встало на свои места.
Рыспэкт! Разобрался в 2 минуты!
Жаль в оракле старый синтаксис, ansi join там только начинает приживаться в новых версиях, например в materialized views при автообновлении он неподдерживается, а сам ansi join довольно неплохой оператор, позволяет избежать мусора (ненужных столбцов) в select.
Кстати, вопрос про старый оракловский синтаксис - если связаный подзапрос (во where) имеет join-связь между несколькими таблицами, как тогда построить запрос? Если используем старый синтаксис, то в select должны перечислить все столбцы, а подзапрос во where должен вернуть одно единственное значение, соответственно поверх подзапроса ставим select (count, max, min) одного столбца, но тогда теряется связь с главным запросом, так как в оракле область видимости подзапроса только на 1 уровень вверх. Тупик?
С новым ansi join сделать подобный запрос не составит труда, так как не нужно всю кучу столбцов извлекать в select.
Спасибо огромное ! Ваша статья помогла и выручила ![]()
Норм статья, по ней понял что такое left join
Файно розписано. Дзенькую.אַ דאַנק Köszönöm
Спасибо за статью! Прекрасные примеры быстро помогли вспомнить не так давно забытое)