Проблема с LEFT JOIN.

Модераторы: kdv, CyberMax

Ответить
beresa
Сообщения: 9
Зарегистрирован: 05 дек 2007, 16:45

Проблема с LEFT JOIN.

Сообщение beresa » 05 дек 2007, 18:39

Изображение

Уважаемые, помогите разобраться.
У меня в базе есть отношение таблиц многие-ко-многим (рис. 1). Так вот, с помощью внешнего левого соединения хотел бы вытащить людей (таблица PERSON), связанных (и не связанных) с определённой работой.
Для этого составляю запрос (выбираем людей, занимающихся вязанием):

Код: Выделить всё

SELECT
    a.id_person,
    a.vc_person,
    b.id_make
FROM
    person a LEFT JOIN make b ON
    a.id_person=b.id_person
WHERE   
    b.id_work=1 

В результате получается набор данных, состоящих из 4-ёх строк (см. рисунок). Почему нет ещё одной строки (должен быть Дмитриев, а в столбце id_wok должно по идее стоять null)?

Требуемый набор данных мне удалось получить с помощью подзапроса (см. рисунк):

Код: Выделить всё

SELECT
    a.id_person,
    a.vc_person,
    (SELECT b.id_make
    FROM make b
    WHERE a.id_person=b.id_person and b.id_work=1)
FROM
    person a 
Но в моём случае это не решение проблемы (т.к. в реальной базе значительно больше таблиц и столбцов).

Как всё-таки получить требуемый набор данных?
Почему не работает левое внешнее соединение?

mdfv
Сообщения: 119
Зарегистрирован: 23 май 2006, 15:53

Сообщение mdfv » 05 дек 2007, 19:32

Как раз все отлично работает как и написано в запросе.
В условиях соединения никто не мешает ограничивающие условия ставить. А where работает уже поверх всего соединенного набора.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: Проблема с LEFT JOIN.

Сообщение WildSery » 05 дек 2007, 20:22

beresa писал(а):Как всё-таки получить требуемый набор данных?
Почему не работает левое внешнее соединение?
Внимательно читать статью о JOINS на этом сайте, вникнуть в раздел "Отличие между ON и WHERE"
mdfv писал(а):А where работает уже поверх всего соединенного набора.
Не совсем так. Однако, результат будет идентичен такому алгоритму.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 дек 2007, 22:34

кстати, что за фигня ID_MAKE ??? первичный ключ у таблицы MAKE должен состоять из двух столбцов - ID_PERSON и ID_WORK.

см. www.ibase.ru/devinfo/joins.htm

правда, сначала надо модели правильные строить...

beresa
Сообщения: 9
Зарегистрирован: 05 дек 2007, 16:45

Сообщение beresa » 06 дек 2007, 13:18

Уважаемый kdv, спасибо большое за статью «Использование неявных и явных Join в InterBase и FireBird». Написано понятно и доступно. Прочитал и сразу «врубился», что для получения требуемого набора данных запрос нужно было строить следующим образом:

Код: Выделить всё

SELECT 
    a.id_person, 
    a.vc_person, 
    b.id_make 
FROM 
    person a LEFT JOIN make b ON 
    a.id_person=b.id_person and  b.id_work=1
Всё работает так как надо! А насчёт избыточности (ID_MAKE),- да, всё понял – первичный ключ действительно нужно составлять из ID_WORK и ID_PERSON. Спасибо за указание!
:D

ODIN
Сообщения: 13
Зарегистрирован: 07 сен 2005, 02:51

Сообщение ODIN » 10 дек 2007, 11:16

если действительно сделать первичный ключ составным из ID_WORK и ID_PERSON то получится что "Александров" сможет один раз в жизни заняться "Вязание"м
моё мнение лучше оставить первичный ключ ID_MAKE или дорабатывать структуру... например извращаться дальше... делать первичный ключ из трёх...четырёх... и тд полей ;) или накатывать unique constraint на необходимые поля

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 10 дек 2007, 18:29

получится что "Александров" сможет один раз в жизни заняться "Вязанием"
в исходной задаче про "один раз в жизни" и т.п. не шло, так что не надо додумывать варианты развития модели за автора топика.

ODIN
Сообщения: 13
Зарегистрирован: 07 сен 2005, 02:51

Сообщение ODIN » 11 дек 2007, 10:34

тоды таблицу называть надо что то в стиле "профориентации сотрудников" (хотяб WORK_PERSON) а не таблица работ... а то получится как вы яхту назовёте так она и поплывёт

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 11 дек 2007, 10:57

ODIN писал(а):а то получится как вы яхту назовёте так она и поплывёт
//OFF я б свою яхту назвал "говно". чтобы непотопляемая была.

Ответить