从一个表中选择所有记录,对于与另一个表中的条件不匹配的行显示0

时间:2013-09-08 13:08:28

标签: sql sql-server join

出于这个问题的目的,我有2张桌子。

  1. 请求:时间戳,会话ID,站点,CampaignID,TagName
  2. 事件:时间戳,会话ID,CampaignID,TagName,InteractionID
  3. 大多数字段都是varchar并允许空值,因为这些是从自定义服务器日志导入的平面文件,有时意外字符可能会从另一个字段泄漏到一个字段 - 我无法控制它。我的要求是提供详细说明唯一网站,广告代码和网站的网站报告。每个广告(标记)在每个网站上投放的次数,以及用户与广告的互动次数,加上点击次数,定义为3个interaction_id(1,2或3)之一。

    运行单独的查询以检查请求中的实际数据:

    SELECT Convert(CHAR(10), r.Timestamp,101) AS [Date]
        , r.Site, r.CampaignID
        , r.TagName, Count(r.TagName) AS TagCount
    
    FROM Requests AS r
    WHERE r.CampaignID = 1901 
    GROUP BY CONVERT(CHAR(10), r.Timestamp,101) , r.Site, r.CampaignID, r.TagName
    ORDER BY [Date], r.Site, r.CampaignID, r.TagName
    

    的产率:

    Date        Site    CampaignID   TagName TagCount
    09/01/2013  Site1   1901          Tag1    61
    09/01/2013  Site1   1901          Tag2    3703
    09/01/2013  Site1   1901          Tag3    279
    09/01/2013  Site2   1901          Tag1    30
    ...
    

    为了得到我尝试的互动次数...

    SELECT CONVERT(CHAR(10), r.Timestamp,101) AS [Date], r.Site, r.CampaignID, r.TagName, Count(r.TagName) As TagCount, Count(e.InteractionID) AS InteractionCount
    FROM Requests AS r
    LEFT JOIN Events as e ON r.SessionID = e.SessionID
    WHERE r.CampaignID = 9101 
    GROUP BY CONVERT(CHAR(10), r.Timestamp,101) ,r.Site, r.CampaignID, r.TagName
    ORDER BY [Date], r.Site, r.CampaignID, e.TagName
    

    的产率:

    Date        Site    CampaignID  TagName TagCount    InteractionCount
    09/01/2013  Site1   9101        Tag1    130         78
    09/01/2013  Site1   9101        Tag2    3805        352
    09/01/2013  Site1   9101        Tag3    307         53
    09/01/2013  Site2   9101        Tag1    30          0
    ...
    

    我的问题/问题。 TagCount上升了,这让我感到惊讶。我可以理解,由于连接条件,它会如何下降,但为什么要上升?在我看来,第一个查询应该计算所有可用的记录,第二个查询不应该找到更多的计数。它必须是我对左连接不了解的东西。那么我如何从请求中获取TagCount以便它只计算所有这些,然后从每个站点的事件中获取InteractionCount。标签名称。我不熟悉SQL来提出一个能够获得正确结果的子查询,但我猜这就是答案所在。

    我的问题的最后一部分是Clicks

    Where e.InteractionID = '1' OR e.InteractionID = '2' OR e.InteractionID = '3'
    

    将我的结果集限制为仅包含点击的记录,但我需要左侧的其余记录,如果没有点击,则需要0,以及满足这些条件的任何计数的总和。

    我希望我已经清楚这些问题了,感谢您的时间和精力,提前致谢。

2 个答案:

答案 0 :(得分:2)

如果时间戳在组中是唯一的,那么:

select
    convert(char(10), r.Timestamp, 101) as [Date],
    r.Site, r.CampaignID, r.TagName,
    count(distinct r.SID) as TagCount,
    count(e.InteractionID) as InteractionCount,
    count(case when e.InteractionID in (1, 2, 3) then e.InteractionID end) as ClicksCount
from Requests as r
    left outer join Events e on e.SessionID = r.SessionID
where r.CampaignID = 9101 
group by
    convert(char(10), r.Timestamp, 101), r.Site, r.CampaignID, r.TagName
order by [Date], Site, CampaignID, TagName;

答案 1 :(得分:1)

标记计数上升的原因是因为您在计算行,而不是不同的值。您可以使用count(distinct)来解决此问题。问题是什么是正确的论点。显然,tagName不是正确的参数,因为您按该字段进行分组。请求ID可以使用,但它不可用。这可能有效:

SELECT CONVERT(CHAR(10), r.Timestamp,101) AS [Date], r.Site, r.CampaignID, r.TagName,
       Count(distinct r.sID) As TagCount, Count(e.InteractionID) AS InteractionCount
FROM Requests r LEFT JOIN
     Events e
     ON r.SessionID = e.SessionID
WHERE r.CampaignID = 9101 
GROUP BY CONVERT(CHAR(10), r.Timestamp,101) ,r.Site, r.CampaignID, r.TagName
ORDER BY [Date], r.Site, r.CampaignID, e.TagName;

换句话说,当您进行连接时,您将从left join获取重复的行。这些都是计数倍数。

如果上述方法不起作用,则需要将计算作为子查询进行,然后进行连接:

select r.[Date], r.Site, r.CampaignID, r.TagName, r.TagCount,
       count(e.InteractionID) as InteractionCount
from (SELECT Convert(CHAR(10), r.Timestamp,101) AS [Date], r.Site, r.CampaignID
             r.TagName, Count(r.TagName) AS TagCount
      FROM Requests r
      WHERE r.CampaignID = 1901 
      GROUP BY CONVERT(CHAR(10), r.Timestamp, 101), r.Site, r.CampaignID, r.TagName
     ) r join
     events e
     ON r.SessionID = e.SessionID
ORDER BY [Date], r.Site, r.CampaignID, r.TagName;