Внутренний Объединение двух таблиц на основе всех пар "ключ / значение", точно совпадающих - PullRequest
2 голосов
/ 03 марта 2010

Допустим, у меня есть две таблицы - Персона и Одежда, и обе эти таблицы имеют связанные таблицы «Ключ / Значение», в которых хранятся атрибуты о Персоне и предмете одежды.

Присоединенная версия Person to Attributes может выглядеть следующим образом:

 PersonID | AttributeKey | AttributeValue
    1          'Age'          '20'
    1          'Size'         'Large'
    2          'Age'          '20'

Присоединенная версия одежды для атрибутов может выглядеть следующим образом:

 ClothingID | AttributeKey | AttributeValue
    99          'Age'          '20'
    99          'Color'        'Blue'
    60          'Age'          '20'

Учитывая конкретный предмет одежды, я хочу найти записи человека, которые точно соответствуют ВСЕМ парам атрибутов. Например, учитывая идентификатор одежды 60, я хочу получить ТОЛЬКО PersonID 2, даже если PersonID 1 имел соответствующий ВОЗРАСТ, но у него были дополнительные атрибуты. И в основном обратное имеет тот же эффект.

Учитывая Одежда 99, я не ожидал бы НЕТ результатов, так как ни одна запись Person не имеет атрибута Color.

ВНУТРЕННЕЕ СОЕДИНЕНИЕ, очевидно, дает мне Атрибуты Одежды, которые соответствуют определенным Атрибутам Людей. Но я хочу вернуть только те строки, в которых ВСЕ возможные совпадения действительно совпадали, и выбросить остальные, если они были лишними. OUTER JOIN даст мне значения NULL для тех, которые соответствуют, но как я это обнаружу и выкину все строки Person, если в 1 строке было NULLS?

Ответы [ 3 ]

2 голосов
/ 03 марта 2010
SELECT  *
FROM    persons p
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    (
                SELECT  key, value
                FROM    clothing_attributes
                WHERE   clothing_id = 99
                ) ca
        FULL JOIN
                (
                SELECT  key, value
                FROM    person_attributes
                WHERE   person_id = p.id
                ) pa
        ON      ca.key = pa.key
                AND ca.value = pa.value
        WHERE   ca.key IS NULL OR pa.key IS NULL
        )
1 голос
/ 03 марта 2010

Вы можете использовать подзапрос, чтобы проверить, что все требования были выполнены. Для каждой комбинации PersonID и ClothingID inner join должно иметь count(*), равное количеству условий в таблице person.

Пример запроса:

select p.PersonID, c.ClothingID
from @person p
inner join @clothing c
    on p.AttributeKey = c.AttributeKey
    and p.AttributeValue = c.AttributeValue
group by p.PersonID, c.ClothingID
having count(*) = (
    select count(*) 
    from @person p2 
    where p.PersonID = p2.PersonID
)

Выход:

PersonID   ClothingID
2          60
2          99

Данные, использованные для проверки запроса:

declare @person table (PersonID int, AttributeKey varchar(30),
    AttributeValue varchar(30))
declare @clothing table (ClothingID int, AttributeKey varchar(30),
    AttributeValue varchar(30))

insert into @person select 1, 'Age', '20'
insert into @person select 1, 'Size', 'Large'
insert into @person select 2, 'Age', '20'

insert into @clothing select 99, 'Age', '20'
insert into @clothing select 99, 'Color', 'Blue'
insert into @clothing select 60, 'Age', '20'
0 голосов
/ 03 марта 2010

Примерно так:

SELECT p.*,c.* People p INNER JOIN Cloths c ON (P.key=c.key AND p.value=c.value) WHERE c.id=99

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