Sql 查询按分组并从多个列表中排除

Sql 查询按分组并从多个列表中排除,sql,tsql,Sql,Tsql,我有一个SQL表(Email\u活动),其中包含我们运行的活动的主列表: Name DateSent Campaign01 01/01/2011 Campaign02 01/15/2011 .. Campaign40 10/01/2011 我有一份客户名单(收到的电子邮件),上面有他们的会员号码和他们收到的活动: PK MembershipNo CampaignName 1 123456 Campaign01 2

我有一个SQL表(Email\u活动),其中包含我们运行的活动的主列表:

Name            DateSent
Campaign01    01/01/2011
Campaign02    01/15/2011
..
Campaign40    10/01/2011
我有一份客户名单(收到的电子邮件),上面有他们的会员号码和他们收到的活动:

PK    MembershipNo    CampaignName
1           123456      Campaign01
2           123456      Campaign02
3           987654      Campaign05
4           111111      Campaign10
我还有一份客户会员号(客户)的主列表

问题:如何编写查询以列出每个活动并统计未收到该电子邮件的客户数?例如(“Received”(已接收)列仅在此处显示以供参考,并不是必需的,因为我知道如何计算):


这里有一种标准的SQL编写方法:

SELECT ec.Name, count(c.MembershipNo) AS DidNotReceive
  FROM Customers AS c
     , Email_Campaigns AS ec
 WHERE NOT EXISTS (
    SELECT 1
      FROM Email_Received AS r
     WHERE er.CampaignName = ec.CampaignName
       AND er.MembershipNo = c.MembershipNo)
 GROUP BY ec.Name
 ORDER BY ec.Name;

这里有一种标准的SQL编写方法:

SELECT ec.Name, count(c.MembershipNo) AS DidNotReceive
  FROM Customers AS c
     , Email_Campaigns AS ec
 WHERE NOT EXISTS (
    SELECT 1
      FROM Email_Received AS r
     WHERE er.CampaignName = ec.CampaignName
       AND er.MembershipNo = c.MembershipNo)
 GROUP BY ec.Name
 ORDER BY ec.Name;
这是最简单的层次。可能还需要考虑其他因素,例如在分发活动时,某个客户是否处于活动状态


这是最简单的层次。可能还需要考虑其他因素,例如在分发活动时,某个客户是否处于活动状态

这应该比我的答案快。然而,我的回答也涵盖了收到的
电子邮件中重复条目的情况(人们可能会收到多封电子邮件,无论是有意还是无意),这一点在问题中并未排除。可以使用计数(不同的x)进行修复。不确定tsql中是否允许这样做。@ErwinBrandstetter T-SQL具有
COUNT(DISTINCT x)
。这应该比我的答案快。然而,我的回答也涵盖了收到的
电子邮件中重复条目的情况(人们可能会收到多封电子邮件,无论是有意还是无意),这一点在问题中并未排除。可以使用计数(不同的x)进行修复。不确定tsql中是否允许这样做。@ErwinBrandstetter T-SQL具有
计数(不同的x)
。要解决以下问题。。。是的,当然也有客户收到多封电子邮件的情况,这是出于设计。要解决以下问题。。。是的,当然也有客户收到多封电子邮件的情况,这是出于设计。谢谢!我很高兴我问了你,因为我之前就有你所拥有的,除了“和”条款。。。难怪查询旋转了15分钟以上却没有结果:-/@hurleystylee:如果你的具体情况允许,你也应该试试Joe Stefanelli的答案,在大桌子上可能会快得多。如果需要,添加我提到的
不同的
。谢谢!我很高兴我问了你,因为我之前就有你所拥有的,除了“和”条款。。。难怪查询旋转了15分钟以上却没有结果:-/@hurleystylee:如果你的具体情况允许,你也应该试试Joe Stefanelli的答案,在大桌子上可能会快得多。如果需要,添加我提到的
不同的
SELECT er.CampaignName, 
       COUNT(*) AS Received, 
       (SELECT COUNT(*) FROM Customers) - COUNT(*) AS DidNotReceive
    FROM Email_Received er
    GROUP BY er.CampaignName
    ORDER BY er.CampaignName;