返回仅匹配给定IN值的* all *的记录

时间:2015-03-19 20:43:06

标签: sql sql-server tsql

有问题的表格:

Persons
-------------------
PersonID (PK)
FirstName
LastName


Descriptors
-------------------
DescriptorID (PK)
Description


PersonDescriptors
-------------------
PersonID (PK)(FK)
DescriptorID (PK)(FK)

您好,

我有三个表:Persons,Descriptors和PersonDescriptors。我试图找出一个查询:

  • 列出可能的人DescriptorID列表(例如:22,11,9等)

  • 读取实际人物描述符记录的PersonDescriptors表(前排:PersonID:107,DescriptorID:22)

  • 仅当所有提供的DescriptorID匹配时才返回匹配的PersonID

例如,PersonID 107有金色头发(DescriptorID:22),因此在PersonDescritors中有一行为107/22。 PersonID 107也有胡子(DescriptorID:11)因此在107/11的PersonDescriptors中有另一行。如果我给查询这两个DescriptorID(22,11),它应该返回PersonID 107.但是如果我给出查询22,11& 9,它不应该返回PersonID 107,因为PersonDescriptors中没有107/9行。

PersonDescriptors中有大约一百万行。

你会如何编码?

一个想法是使用WHERE NOT EXISTS语句,但我的尝试太慢(在本地SQL Server 2014实例上超过20秒):

SELECT DISTINCT pd1.PersonID FROM PersonDescriptors pd1

WHERE NOT EXISTS (

    SELECT 1 FROM PersonDescriptors pd2 WHERE NOT EXISTS (

        SELECT 1 FROM PersonDescriptors pd3 
        WHERE 
                pd3.PersonID = pd1.PersonID
            AND pd3.DescriptorID = pd2.DescriptorID

    ) 
    AND pd2.DescriptorID IN (1, 71) --two descriptors. more even slower
);

...另一个是接受目标DescriptorID的XML并将它们加载到临时表中,每个DescriptorID一行,并尝试一些JOIN魔法,但我无法弄清楚。

另一个想法是使用IN条件数量的HAVING COUNT,但我也无法将其拉出来。

我缺少或有帮助的想法?谢谢!

1 个答案:

答案 0 :(得分:2)

使用group byhaving

select pd.PersonId
from PersonDescriptors pd
where pd.DescriptorID IN (1, 71)
group by pd.PersonId
having count(distinct pd.DescriptorID) = 2;

您可以轻松地将其概括为任意长度的列表。请记住在having子句中更改常量。