1

我想从一个表中提取与所有指定值匹配的结果,其中指定值在另一个表中。我可以这样做:

SELECT * FROM Contacts 
WHERE 
EXISTS (SELECT 1 FROM dbo.ContactClassifications WHERE ContactID = Contacts.ID AND ClassificationID =  '8C62E5DE-00FC-4994-8127-000B02E10DA5')
AND EXISTS (SELECT 1 FROM dbo.ContactClassifications WHERE ContactID = Contacts.ID AND ClassificationID =  'D2E90AA0-AC93-4406-AF93-0020009A34BA')
AND EXISTS etc...

然而,当我得到大约 40 个 EXISTS 子句时,这种情况就会失败。错误消息是“查询处理器用完内部资源,无法生成查询计划。这是一种罕见的事件,仅适用于极其复杂的查询或引用大量表或分区的查询。请简化查询。”

4

3 回答 3

6

这样做的要点是

  • IN从语句中选择具有任何 GUID 的所有联系人
  • 使用 aDISTINCT COUNT在匹配的 GUID 上获取每个联系人 ID 的计数
  • 使用HAVING仅保留与您在IN语句中输入的匹配 GUID 数量相等的联系人

SQL 语句

SELECT *
FROM   dbo.Contacts c
       INNER JOIN (
          SELECT c.ID
          FROM   dbo.Contacts c
                 INNER JOIN dbo.ContactClassifications cc ON c.ID = cc.ContactID
          WHERE  cc.ClassificationID IN ('..', '..', 38 other GUIDS)
          GROUP BY
                 c.ID
          HAVING COUNT(DISTINCT cc.ClassificationID) = 40
       ) cc ON cc.ID = c.ID

data.stackexchange上的测试脚本

于 2012-06-05T16:34:07.680 回答
3

一种解决方案是要求在没有匹配联系人的情况下不存在分类。这是双重否定:

select  *
from    contacts c
where   not exists
        (
        select  *
        from    ContactClassifications cc
        where   not exists
                (
                select  *
                from    ContactClassifications cc2
                where   cc2.ContactID = c.ID
                        and cc2.ClassificationID = cc.ClassificationID
                )
        )

这种类型的问题被称为关系划分

于 2012-06-05T16:29:43.860 回答
0
SELECT c.* 
FROM Contacts c
INNER JOIN 
 (cc.ContactID, COUNT(DISTINCT cc.ClassificationID) as num_class
  FROM ContactClassifications 
  WHERE  ClassificationID IN (....)
  GROUP BY cc.ContactID 
 ) b ON c.ID = b.ContactID
WHERE b.num_class = [number of distinct values - how many different values you put in "IN"]

如果您运行 SQLServer 2005 及更高版本,您可以使用 执行几乎相同的操作CROSS APPLY,据说效率更高

于 2012-06-05T16:32:29.837 回答