Выборка из таблицы объектов по таблице связей

Bible_Black

Новичок
Выборка из таблицы объектов по таблице связей

Имеются две таблицы:

1) Таблица объектов
Objects
-----------------------------
id
type

2) Таблица связей между объектами
Relations
-----------------------------
parentId
childId
relationType

Требуется выбрать из талицы Objects все объекты типа A (Objects.type='A') не связанные в таблице Relations ни с одним объектом типа B (Objects.type='B') по связи relationA (Relations.relationType='relationA')

Например для двух таблиц:

id type
1 A
2 B
3 D

и

parentId childId relationType
1 2 relationA
1 3 relationB
3 1 relationA
3 2 relationB

необходимо получить объект с id=3, не связанный ни с одним объектом типа B по связи relationA

Пока есть только вариант со временной таблицей, но возможно-ли получить требуемый результат как-то иначе, например при помощи LEFT JOIN?
 

zerkms

TDD infected
Команда форума
м?
[sql]
SELECT * FROM `Objects` `o`
LEFT JOIN `Relations` `r` ON `r`.`parentId` = `o`.`id` AND `r`.`childId` = 2 AND `r`.`relationType` = 'relA'
WHERE `relationType` IS NULL
[/sql]

не проверял
 

Bible_Black

Новичок
zerkms не совсем верно поняли вопрос. В том то и дело, что childId не известен, его вообще может не быть, известны только тип связи и тип связанных объектов и требуется извлечь объекты для которых нет данного типа связи с данным типом объектов!
 

zerkms

TDD infected
Команда форума
и чем мой запрос не удовлетворяет твоим требованиям?
попробовал - он возвращает B и D
согласно твоим требованиям ни у B ни у D нет связей с объектом класса B (да, повторы легко можно убрать) с типом связи relationA
 

Bible_Black

Новичок
Это ясно, но нужно получить объекты у которых НЕТ(!) связей типа A ИМЕННО(!) с объектами типа B. Причём не исключается возможность связей типа A с другими типами объектов или связей другого типа с объектами типа B!
 

zerkms

TDD infected
Команда форума
[sql]
SELECT * FROM `o`
LEFT JOIN `r` `r1` ON `r1`.`parent` = `o`.`id` AND `r1`.`child` = 2 AND `r1`.`relType` = 'relA'
WHERE `r1`.`relType` IS NULL AND `o`.`id` != 2
[/sql]

Код:
+------+------+--------+-------+---------+
| id   | name | parent | child | relType |
+------+------+--------+-------+---------+
|    3 | D    |   NULL |  NULL | NULL    |
+------+------+--------+-------+---------+
1 row in set (0.00 sec)
что я делаю не так?
 

Bible_Black

Новичок
Вот этого

`r1`.`child` = 2

в условии нет. Известен только тип дочерних объектов. Информации о типе в таблице связей нет!
 

zerkms

TDD infected
Команда форума
[sql]
SELECT * FROM `o`
INNER JOIN `o` `o2` ON `o2`.`name` = 'B'
LEFT JOIN `r` `r1` ON `r1`.`parent` = `o`.`id` AND `r1`.`child` = `o2`.`id` AND `r1`.`relType` = 'relA'
WHERE `r1`.`relType` IS NULL AND `o`.`id` != `o2`.`id`
[/sql]

???

Информации о типе в таблице связей нет!
если нет, то как происходит связь тогда???????
 

Bible_Black

Новичок
Таким образом таблицу Objects придётся цеплять в любом случае 2 раза: для выборки только объектов типа A и только связанных с ними по типу С объектов типа B.

Таким образом ещё раз уточню результат должно быть

такие A, что не существует цепочки A-C-B

-~{}~ 19.03.07 11:36:

Объекты свзываются следующим образом

Идентификатор родительского - Идентификатор дочернего - Тип связи

-~{}~ 19.03.07 11:36:

То есть из таблицы связей невозможно узнать какого типа объекты связаны!
 

zerkms

TDD infected
Команда форума
я уже ничего не понимаю. или я тупой или кто-то совершенно не умеет объяснять что у него есть и что ему нужно ;)
 

Bible_Black

Новичок
Решил задачу следующим запросом

SELECT A.* FROM object A
WHERE (A.objectType='type1') AND (A.objectId NOT IN (SELECT B.parentId FROM relation B, object C WHERE (B.relationType='relation1') AND (B.childId=C.objectId) AND (C.objectType='type2')))
 

zerkms

TDD infected
Команда форума
То есть из таблицы связей невозможно узнать какого типа объекты связаны!
тогда зачем существует таблица связей если из неё как оказывается почти никакой полезной информации почерпнуть невозможно? или ты что-то снова умалчиваешь?
 

Bible_Black

Новичок
Таким образом выбираются все объекты типа "type1" не имеющие связей типа "relation1" с объектами типа "type2"

-~{}~ 19.03.07 11:43:

А зачем дублировать информацию о типах объектов в таблице связей??? Таблица связей нужна чтобы соединить уникальные идентификаторы двух объектов и указать каким образом!

-~{}~ 19.03.07 11:45:

zerkms спасибо за попытку помочь!

-~{}~ 19.03.07 11:48:

Можем потолковать о структуре системы, но наверно вынести это в отдельную тему!
 

zerkms

TDD infected
Команда форума
ужасный запрос......
в котором к тому же содержатся данные (условия) которые в изначальном вопросе не упоминались ;)

(я про то - что ты сам запрашиваешь конкретно type1 и type2) :)

-~{}~ 19.03.07 18:50:

и всё таки, у меня уже исключительно спортивный интерес
почему запрос
[sql]
SELECT *
FROM `o`
INNER JOIN `o` `o2` ON `o2`.`name` = 'B' AND `o`.`id` != `o2`.`id`
LEFT JOIN `r` `r1` ON `r1`.`parent` = `o`.`id` AND `r1`.`child` = `o2`.`id` AND `r1`.`relType` = 'relA'
WHERE `r1`.`relType` IS NULL
[/sql]
всё таки не решает поставленной задачи?
 

Bible_Black

Новичок
Не решает, он вообще решает что-то совершенно другое :)
Хотя бы потому что в нём не указан ни разу тип объектов, ни того что является родителем, ни дочерних (а это ключевой момент задачи)!

Ещё раз объясню максимально полно задачу:

1) Имеются объекты различных типов с уникальными идентификаторами (тип и идентификатор задаются в таблице Objects)
2) Между объектами могут существовать связи различных типов. Связь задаётся тремя параметрами: идентификатор родительского объекта, идентификатор дочернего, тип связи. Для простоты пусть любой объект может быть связан с любым другим (в том числе и сам с собой, петля) по любому типу связи.
3) Задача - сделать выборку объектов типа A, для которых не существует связей типа B с объектами типа С. То есть показать отсутствие цепочки связей A-B-C!
4) Объекты ни коем образом не фильтруются, там по имени или идентификатору, нужно извлечь все объекты типа A!
5) Таким образом нам известны: тип объектов A, тип связи B, тип объектов С, ничего более!

-~{}~ 19.03.07 12:28:

Странно, но вот то что я писал в начале:

Требуется выбрать из талицы Objects все объекты типа A (Objects.type='A') не связанные в таблице Relations ни с одним объектом типа B (Objects.type='B') по связи relationA (Relations.relationType='relationA')

Это таже задача. И ещё вопрос, почему мой запрос плох, по времени или по каким критериям?

-~{}~ 19.03.07 12:29:

Мой запрос выбирает все объекты типа 'type1' для которых отсутствует связь type1-relation1-type2

-~{}~ 19.03.07 12:33:

То есть мне нужно контролировать не просто relation1 IS NULL, а более точно relation1 с объектом type2 IS NULL!
 
Сверху