Страница 1 из 1

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

Добавлено: 05 дек 2007, 18:39
beresa
Изображение

Уважаемые, помогите разобраться.
У меня в базе есть отношение таблиц многие-ко-многим (рис. 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 
Но в моём случае это не решение проблемы (т.к. в реальной базе значительно больше таблиц и столбцов).

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

Добавлено: 05 дек 2007, 19:32
mdfv
Как раз все отлично работает как и написано в запросе.
В условиях соединения никто не мешает ограничивающие условия ставить. А where работает уже поверх всего соединенного набора.

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

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

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

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

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

Добавлено: 06 дек 2007, 13:18
beresa
Уважаемый 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

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

Добавлено: 10 дек 2007, 18:29
kdv
получится что "Александров" сможет один раз в жизни заняться "Вязанием"
в исходной задаче про "один раз в жизни" и т.п. не шло, так что не надо додумывать варианты развития модели за автора топика.

Добавлено: 11 дек 2007, 10:34
ODIN
тоды таблицу называть надо что то в стиле "профориентации сотрудников" (хотяб WORK_PERSON) а не таблица работ... а то получится как вы яхту назовёте так она и поплывёт

Добавлено: 11 дек 2007, 10:57
WildSery
ODIN писал(а):а то получится как вы яхту назовёте так она и поплывёт
//OFF я б свою яхту назвал "говно". чтобы непотопляемая была.