2010-05-06 89 views
2

我有一个表活动,其中包含发送活动邮件的详细信息。如何使用连接编写此查询?

campaign_table: campaign_id campaign_name flag 
         1   test1  1 
         2   test2  1 
         3   test3  0 

另一个表具有活动活动细节的活动活动。

campaign_activity: campaign_id is_clicked is_opened 
          1    0   1   
          1    1   0   
          2    0   1 
          2    1   0 

我想用标志值3和值为1和列数is_clicked列与is_opened值1在一个查询数所有广告活动。

ie. campaign_id campaign_name numberofclicks numberofopens 
      1   test1   1    1 
      2   test2   1    1 

我这样做是使用子查询与查询:

select c.campaign_id,c.campaign_name, 
(SELECT count(campaign_id) from campaign_activity WHERE campaign_id=c.id AND is_clicked=1) as numberofclicks, 
(SELECT count(campaign_id) from campaign_activity WHERE campaign_id=c.id AND is_clicked=1) as numberofopens 
FROM 
campaign c 
WHERE c.flag=1 

但人们说,使用子查询是不是一个很好的编码习惯,你必须使用联接,而不是子查询。但我不知道如何使用连接获得相同的结果。我咨询了一些同事,他们说在这种情况下不可能加入。使用连接可以得到相同的结果吗?如果是,请告诉我如何。

+0

它通常OK使用WHERE子句中的子查询,但要避免使用它们作为列。 – 2010-05-06 09:39:36

回答

4

这应该可以做到。如果您想要包含没有任何活动的广告系列,请将INNER JOIN替换为LEFT OUTER JOIN。

SELECT 
    c.Campaign_ID 
    , c.Campaign_Name 
    , SUM(CASE WHEN a.Is_Clicked = 1 THEN 1 ELSE 0 END) AS NumberOfClicks 
    , SUM(CASE WHEN a.Is_Opened = 1 THEN 1 ELSE 0 END) AS NumberOfOpens 
FROM 
    dbo.Campaign c 
INNER JOIN 
    dbo.Campaign_Activity a 
ON a.Campaign_ID = c.Campaign_ID 
GROUP BY 
    c.Campaign_ID 
    , c.Campaign_Name 
+0

'CASE WHEN a.Is_XXXX <> 0 THEN 1 ELSE 0 END'可能是一个更好的主意,所有非零值返回1,零和NULL返回0。 – 2010-05-06 09:52:06

+0

不错;使用'case'语句,您还可以轻松地将“inner join”更改为“left outer join”,以捕获活动表中没有条目的广告系列。 – tzaman 2010-05-06 11:18:18

+0

@Salman:在技术上,OP确实要求计数值为1的列,而不是非零/ null,所以这是正确的。 – tzaman 2010-05-06 11:19:49

0

我想这应该这样做:

select * from campaign_table inner join campaign_activity on campaign_table.id = campaign_activity.id where campaign_table.flag = 3 and campaign_activity.is_clicked = 1 and campaign_activity.is_opened = 1 

经办人:这是不带电情况下

+0

我想获得is_clicked和is_opened的计数,其值为1.不只是列。 – aquero 2010-05-06 09:20:00

2

嗯测试。你想这么简单吗?我不知道我读题吧......

SELECT 
    campaign_table.campaign_id, SUM(is_clicked), SUM(is_opened) 
FROM 
    campaign_table 
    INNER JOIN campaign_activity ON campaign_table.campaign_id = campaign_activity.campaign_id 
WHERE 
    campaign_table.flag = 1 
GROUP BY 
    campaign_table.campaign_id 

注意与INNER JOIN在这里,你将不会看到广告,其中有一个在campaign_activity表中对应的什么都没有。在这种情况下,应该使用LEFT JOIN,并在SUM中将NULL转换为0。 SUM(IFNULL(is_clicked,0))。

4

假设is_clickedis_opened是永远只1或0,这应该工作:

select c.campaign_id, c.campaign_name, sum(d.is_clicked), sum(d.is_opened) 
from campaign c inner join campaign_activity d 
on c.campaign_id = d.campaign_id 
where c.flag = 1 
group by c.campaign_id, c.campaign_name 

无子查询。

+1

如果'is_clicked'和'is_opened'不只是1或0,你可以使用 SUM(IF(is_clicked = 1,1,0))' – 2010-05-06 09:16:26

+0

@Draco:很好的调整! – tzaman 2010-05-06 09:38:52

+0

您可能希望使用'left join'来检索那些没有相应活动的活动;对于这样的行,“SUM”列将包含“NULL”。 – 2010-05-06 09:44:45

0

在它最简单的形式和最强大的形式SQL是这样的:(格式化的可读性)

SELECT 
campaign_table.campaign_ID, campaign_table.campaign_name, Sum(campaign_activity.is_clicked) AS numberofclicks, Sum(campaign_activity.is_open) AS numberofopens 

FROM 
campaign_table INNER JOIN campaign_activity ON campaign_table.campaign_ID = campaign_activity.campaign_ID 

GROUP BY 
campaign_table.campaign_ID, campaign_table.campaign_name, campaign_table.flag 

HAVING 
campaign_table.flag=1;