内部基于完全匹​​配的所有“键/值”对连接两个表

时间:2010-03-02 23:17:05

标签: sql-server database tsql join

假设我有两个表 - Person和Clothes,这两个表都有关联的Key / Value表,用于存储有关Person和服装项的属性。

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'

给定一件特定的衣服,我想找到与所有属性对完全匹配的Person条目。例如,给定ClothingID 60,我想获得PersonID 2,即使PersonID 1确实具有匹配的AGE,但它具有额外的属性。而基本上相反的效果也是如此。

给定服装99我会期望没有结果,因为没有Person条目具有Color属性。

INNER JOIN显然给了我符合人物特定属性的服装属性。但我想只返回所有可能的匹配确实匹配的行,如果有额外的则抛出其他行。一个OUTER JOIN会给我一些匹配的NULL值但我如何检测到这个并抛出所有Person行,如果有一行有NULLS?

3 个答案:

答案 0 :(得分:2)

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 :(得分:1)

您可以使用子查询来验证是否已满足所有要求。对于PersonID和ClothingID的每个组合,inner join应该有count(*),等于人员表中的条件数。

示例查询:

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'

答案 2 :(得分:0)

这样的事情:

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