Как сделать пересечение на композиционной таблице - PullRequest
0 голосов
/ 19 марта 2012

У меня есть простая реляционная модель SQL с отношением многие ко многим. Вот состав таблицы

 ___________________________
| object1_id  | object2_id  |
|---------------------------|

Я хотел бы знать все object1, которые являются общими для набора object2. Мое основное чувство - сделать запрос, подобный этому

SELECT c.object1_id FROM composition c WHERE c.object2_id = <given_id_1>
INTERSECT 
SELECT c.object1_id FROM composition c WHERE c.object2_id = <given_id_2>

И если у меня в наборе N object2, я сделаю N INTERSECT

SELECT c.object1_id FROM composition c WHERE c.object2_id = <given_id_1>
INTERSECT 
SELECT c.object1_id FROM composition c WHERE c.object2_id = <given_id_2>
...
INTERSECT 
SELECT c.object1_id FROM composition c WHERE c.object2_id = <given_id_N>

Однако, это выглядит не очень оптимизированным. Вы можете мне помочь ? Я не совсем эксперт по SQL. Я думаю, что я мог бы использовать JOIN, чтобы сделать это.

Sample

 ___________________________
| object1_id  | object2_id  |
|---------------------------|
|         10  |           1 |
|         11  |           1 |
|         10  |           2 |
|         12  |           2 |
|         10  |           3 |
|         11  |           3 |
|         13  |           3 |

Пример * ** тысяча двадцать-один * тысяча двадцать два {object2_id set} => {ожидается object1_id} {1, 2} => {10} {1, 3} => {10, 11} {1, 2, 3} => {10}

Ответы [ 3 ]

2 голосов
/ 19 марта 2012

С точки зрения производительности ваш запрос выглядит нормально.Вы измерили его, чтобы увидеть, действительно ли существует проблема?

Если (object1_id, object2_id) уникален, вы можете написать запрос более кратко следующим образом:

SELECT object1_id
FROM composition
WHERE object2_id IN (id1, id2, ..., id6)
GROUP BY object1_id
HAVING COUNT(*) = 6

Обратите внимание, что 6 количество предоставленных идентификаторов.Это следует изменить, если указано другое количество идентификаторов.Вам нужно измерить фактическую производительность вашей дадты, чтобы увидеть, дает ли это какое-либо увеличение скорости.

Если вы не можете предполагать уникальность, тогда это должно работать:

SELECT object1_id
FROM composition
WHERE object2_id IN (id1, id2, ..., id6)
GROUP BY object1_id
HAVING COUNT(DISTINCT object2_id) = 6

Самое важноеТем не менее, нужно убедиться, что у вас на столе есть indexes !Это далеко важнее, чем когда вы пишете один или другой запрос.

1 голос
/ 19 марта 2012

Я считаю, что это должно работать.Он найдет все композиции 1, которые также имеют композицию 2, которая соответствует.Если я не понимаю, что вы ищете.Если да, не могли бы вы предоставить пример данных?

SELECT c1.object_id 
FROM Composition AS c1
WHERE EXISTS 
    (
        SELECT 1
        FROM Composition c2
        WHERE c2.object2_id = c1.object1_id
        --Add an AND to only look for a certain set of c2's
        --AND c2.object2_id IN (SET of object2id's)
    )
0 голосов
/ 20 марта 2012

Я думаю, что это вопрос реляционного деления .

Аналогия: найдите поставщика, который поставляет все детали.

object2_id is part_id

object1_id is supplier_id

Запросis,

Найти supplier_id значений для поставщиков, которые поставляют все детали в наборе part_id значений { 1, 2, 3 }.

Обычно это квалифицировано у

... поставщиков, которые поставляют хотя бы одну деталь и ...

в противном случае у всех поставщиковбудет поставлять пустой набор деталей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...