-- таблица цветовcreate table colors(id integer,cname varchar(45), -- название цвета constraint pk_colors primary key (id)); insert into colors values(1,'красный');insert into colors values(2,'синий');insert into colors values(3,'зеленый');insert into colors values(4,'белый');insert into colors values(5,'черный');insert into colors values(6,'бурмалиновый'); -- таблица объектов мираcreate table objs (id integer,oname varchar(45), -- название объектаfk integer, -- ссылка на цвет объекта constraint pk_objs primary key (id),constraint fk_objs foreign key (fk) references colors(id) ); insert into objs values(1,'небо',2);insert into objs values(2,'уголь',5);insert into objs values(3,'лист',3);insert into objs values(4,'водка',null );insert into objs values(5,'ягода',1); commit;
Ниже приведен пример запроса из двух таблиц без условия соединения. В результате возвращается выборка из 30 записей, где для каждой записи первой таблицы сопоставлены по очереди все записи второй таблицы, или другими словами, все комбинации. select o.oname, c.cname from objs o, colors c;
Для присоединения к каждой записи первой таблицы, только ту запись из второй таблицы, на которую происходит ссылка, необходимо указать условие. Это можно сделать в конструкции where или в конструкции from. Ниже приведен пример запроса с внутренним соединением.
-- условие в whereselect o.oname, c.cname from objs o, colors c where o.fk=c.id; -- условие в from с помощью-- конструкции JOIN ON select o.oname, c.cname from objs o INNER JOIN colors c ON (o.fk=c.id );
К одному источнику данных можно последовательно присоединять сколько угодно других источников.
select o.oname, c.cname, o2.oname as oname2 from (objs o INNER JOIN colors c ON (o.fk=c.id )) INNER JOIN (select * from objs ) o2 ON (o.id=o2.id)
В нашем случае внутреннего соединения не достаточно, так как из выборки выпадает запись с пустым значением внешнего ключа. Если же поставить условие "o.fk=c.id or o.fk is null", то вновь получим лишние записи. Данная задача решается с помощью внешних соединений. Если по условию для записи одной таблицы не найдено ни одной записи из другой таблицы, то присоединится пустая запись. Слова одной и другой использованы здесь не случайно. При внешних соединениях явно указывается к какой таблице происходит присоединение. В ниже приведенном примере ключевое слово OUTER в большинстве СУБД можно опустить.
-- присоединяем к левой таблице-- в результате в выборке будет 5 записей-- в столбце cname будет одно пустое полеselect o.oname, c.cname from (objs o LEFT OUTER JOIN colors c ON (o.fk=c.id )) -- присоединяем к правой таблице-- в результате в выборке будет 6 записей-- в столбце oname будет два пустых поляselect o.oname, c.cname from (objs o RIGHT OUTER JOIN colors c ON (o.fk=c.id )) -- в расширении Oracle можно указать (+)-- в условии для той таблицы, для которой-- будут генерироваться пустые записиselect o.oname, c.cname from objs o, colors c -- присоединяем к левой таблице where o.fk=c.id(+) select o.oname, c.cname from objs o, colors c -- присоединяем к правой таблице where o.fk(+)=c.id
Пустое значение в выборке можно заменить функцией coalesce.
-- в MySQL между coalesce и скобкой не должно -- быть пробелов. select o.oname, coalesce(c.cname,'цвет не задан') from (objs o LEFT OUTER JOIN colors c ON (o.fk=c.id ));