Sql 如何在没有多个EXISTS子句的情况下返回表中匹配的行?

Sql 如何在没有多个EXISTS子句的情况下返回表中匹配的行?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我想从一个表中提取与所有指定值匹配的结果,其中指定值位于另一个表中。我可以这样做: 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.Cont

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

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条时,这就结束了。错误消息为“查询处理器耗尽内部资源,无法生成查询计划。这是一个罕见的事件,仅适用于极其复杂的查询或引用大量表或分区的查询。请简化查询。”

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

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
                )
        )

这种类型的问题称为。

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

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
                )
        )
这种类型的问题称为

如果运行SQLServer2005及更高版本,则可以使用
交叉应用
执行大致相同的操作,据说效率更高

如果您运行SQLServer2005及更高版本,您可以使用
交叉应用
来执行几乎相同的操作,据说效率更高

本文的要点是

  • 从语句中的
    中选择具有任何GUID的所有联系人
  • 使用
    不同计数
    获取匹配GUID上每个contactid的计数
  • 使用
    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
测试脚本的要点是

  • 语句中的
    中选择具有任何GUID的所有联系人
  • 使用
    不同计数
    获取匹配GUID上每个contactid的计数
  • 使用
    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


测试脚本位于

在ClassificationID上使用IN子句怎么样?IN子句的问题是它匹配任何ClassificationID。我想让它匹配所有ClassificationID,在ClassificationID上使用IN子句怎么样?IN子句的问题是它匹配任何ClassificationID。我希望它匹配所有分类ID…不确定这是否正确,但最终有人阅读了这个问题&他的评论!你需要他的分类号列表在里面somewhere@Gerrat:查询要求联系人具有ContactClassifications表中的所有分类。正如问题所问,“另一个表中的所有值”OP澄清了——他想要所有“指定”值(但我喜欢这种技术)+1在关系分割链接上。如果你听到砰的一声,别担心。。。我的头爆炸了:)…不确定这是否正确,但最后有人读了这个问题&他的评论!你需要他的分类号列表在里面somewhere@Gerrat:查询要求联系人具有ContactClassifications表中的所有分类。正如问题所问,“另一个表中的所有值”OP澄清了——他想要所有“指定”值(但我喜欢这种技术)+1在关系分割链接上。如果你听到砰的一声,别担心。。。这让我头晕目眩:)OP询问“另一个表中的所有值”,并不是所有值都传递到查询,然后放在in子句中。如果您的输入是GUID列表,那么这是一个正确的答案:)@Andomar-thx,我错过了。要进行运算,是否可以假定另一个表不是ContactClassifications?最后,它将使该语句比In语句更不容易出错。IN语句可以替换为内部联接,并且可以在另一个表中查找计数。@Lieven-我不确定您是否理解。输入是用户从复选框列表中选择的GUID列表。复选框列表是从分类表填充的。因此,接触分类就是接触与分类之间的关系。我们希望结果是链接到所有指定分类的所有联系人。这有帮助吗?@Colin-如果您的输入是一个GUID列表,其中联系人应该有每个GUID,那么按原样的语句就足够了。如果这个答案不能回答您的问题,您应该删除accepted标志,让其他人插话。OP询问“另一个表中的所有值”,并不是所有值都传递到查询,然后放在in子句中。如果您的输入是GUID列表,那么这是正确的答案:)@Andomar-thx,我错过了。要进行运算,是否可以假定另一个表不是ContactClassifications?最后,它将使该语句比In语句更不容易出错。IN语句可以替换为内部联接,并且可以在另一个表中查找计数。@Lieven-我不确定您是否理解。输入是用户从复选框列表中选择的GUID列表。复选框列表是从分类表填充的。因此,接触分类就是接触与分类之间的关系。我们希望结果是链接到所有指定分类的所有联系人。这有帮助吗?@Colin-如果您的输入是一个GUID列表,其中联系人应该有每个GUID,那么按原样的语句就足够了。如果这个答案不能回答你的问题,你应该移除接受标志,让其他人插话。