如何修复子查询以阻止LEFT JOIN膨胀计数?

时间:2015-11-18 04:23:51

标签: mysql join count subquery left-join

我有两个表:canvasssurvey。下面是每个的示例模式 - ID匹配,每个都有一些有目的的重复。

游说表

ID  Name              Result        ContactedBy DateContacted ContactType
1   Seinfeld, Jerry   Contacted     Bluth, Gob     3/5/15   Phone
2   Benes, Elaine     Wrong Address Bluth, Gob     4/7/15   Walk
3   Costanza, George  Contacted     Bluth, Michael 9/15/15  Walk
4   Kramer, Cosmo     Contacted     Funke, Tobias  12/14/14 Walk
5   David, Larry      Contacted     Bluth, Michael 11/11/14 Walk
6   Puddy, David      Not Home      Bluth, Michael 4/9/15   Walk
7   Ross, Susan       Not Home      Funke, Tobias  4/19/15  Phone
1   Seinfeld, Jerry   Contacted     Bluth, Gob     9/15/15  Walk
9   Costanza, Frank   Not Home      Funke, Tobias  3/30/15  Walk
10  Cohen, Ruthie     Call Back     Funke, Tobias  12/3/12  Phone

调查表

ID  Name             SurveyId   DateContacted ContactType   ContactedBy
1   Seinfeld, Jerry  99         3/5/15        Phone         Bluth, Gob
2   Benes, Elaine    99         4/7/15        Walk          Bluth, Gob
3   Costanza, George 99         9/15/15       Walk          Bluth, Michael
4   Kramer, Cosmo    88         12/14/14      Walk          Funke, Tobias
5   David, Larry     99         11/11/14      Walk          Bluth, Michael
6   Puddy, David     88         4/9/15        Walk          Bluth, Michael
7   Ross, Susan      11         4/19/15       Phone         Funke, Tobias
1   Seinfeld, Jerry  99         9/15/15       Walk          Bluth, Gob
9   Costanza, Frank  99         3/30/15       Walk          Funke, Tobias
10  Cohen, Ruthie    11         12/3/12       Phone         Funke, Tobias

我的桌子比上面的两个更大更乱,但它应该给出一个想法。这是一个快速的例子,说明我希望看到的结果(即使我没有通过下面的查询得到它):

ContactedBy    Knocked    Contacted     88 SurveyID 99 SurveyID
Bluth, Gob     30           3               3              0
Bluth, Michael 40           3               2              1
Funke, Tobias  10           2               1              1

如果我按表单独运行计数(无论是在一个查询中还是一起使用子查询),我得到了正确的结果 - 但是如果我尝试将它们放在一起,所有的计数都会得到由于LEFT JOIN而非常夸张。我知道这是因为人们有更多的调查而不仅仅是我关心的调查,这复制了每个ID的数量 - 但我无法弄清楚如何阻止它。

这是我在查询中的最佳镜头 - 尽管如上所述 - 尽管它正在查询并产生类似于上面所希望的表格的结果,但它过度膨胀了所有计数:

SELECT a.contactedby, SUM(Knocked), SUM(Contacted), SUM(88), SUM(99)
FROM (SELECT c.id cid,
    c.contactedby,
    c.result,
    c.contacttype,
    c.datecontacted,
    COUNT(c.id) Knocked,
    COUNT(CASE WHEN c.result = "Contacted" THEN c.id ELSE NULL END) Contacted,
    s.id sid,
    s.surveyid,
    COUNT(CASE WHEN s.surveyid = 88 THEN s.id ELSE NULL END) 88,
    COUNT(CASE WHEN s.surveyid = 99 THEN s.id ELSE NULL END) 99
    FROM canvass c
    LEFT JOIN survey s ON s.id = c.id AND RIGHT(s.datecontacted,2)="15" AND s.contacttype = "Walk" AND s.contactedby = c.contactedby
    WHERE RIGHT(c.datecontacted,2)="15" AND c.contacttype = "Walk"
    GROUP BY c.id, c.contactedby
    ORDER BY c.contactedby
) AS a
GROUP BY a.contactedby;

任何帮助解决这个问题将不胜感激!最终游戏正在从查询中获得关于我关注的调查的结果,同时忽略任何未在2015年从步行中获得的表格中的任何内容。

-

我根据下面发布的有用的GROUPing pitfall文章尝试了另一个查询,虽然我没有收到任何错误,但结果是我想要的确切形式,并且敲门/联系的数字都很好,88和99调查主要是NULL个,其中填充了一些随机数。这是查询:

SELECT c.contactedby contby, COUNT(CASE WHEN c.id IS NOT NULL THEN c.id ELSE NULL END) Knocked, COUNT(CASE WHEN c.result = "Contacted" THEN c.id ELSE NULL END) Contacted, s.88, s.99
FROM canvass c
LEFT JOIN
    (
        SELECT s1.id sid, s1.contactedby contby1, COUNT(DISTINCT CASE WHEN s1.surveyid = 88 THEN s1.id ELSE NULL END) 88, COUNT(DISTINCT CASE WHEN s1.surveyid = 99 THEN s1.id ELSE NULL END) 99
        FROM survey s1
        GROUP BY contby1
    ) AS s ON s.sid = c.id
WHERE RIGHT(c.datecontacted,2) = "15" AND c.contacttype = "Walk"

1 个答案:

答案 0 :(得分:2)

简短版本:您无法在同一查询中一次聚合两个表。

您希望编写两个子查询,这些子查询按您想要在主查询中唯一的任何内容进行分组,然后将它们连接在一起。

对于我前一段时间为我的同事写的稍长一些的更详尽的解释,请阅读GROUPing Pitfall上的这篇文章 - 您遇到的问题。它有查询示例和一切!