2015-02-24 64 views
2

我有一个名为SQL鸿沟数据

表如下表:活动

userid appid type 
1   a  imp 
2   a  imp 
2   a  click 
3   a  imp 
4   a  imp 
4   a  click 
5   b  imp 
5   b  click 

我试图计算出每个appid的点击率。在这种情况下,我们将点击率定义为(点击次数)/(展示次数)。我写了下面的SQL:

SELECT appid, type, count(*) from activity group by appid, type 

,并得到了以下结果:

输出:

appid type  count(*) 
a  click  2 
a  imp  4 
b  click  1 
b  imp  1 

下一步是做逐行师。最终,我想实现以下目标:

目标:

appid click-through 
a  .5      # 2/4 = .5 
b  1       # 1/1 = 1 

这是如何实现的呢?理想情况下,我希望这可以在一个查询中完成,那有可能吗?

回答

3

可以使用条件聚集做到这一点:

select appid 
     , SUM(CASE WHEN type = 'click' THEN 1 END)*1.0 
     /SUM(CASE WHEN type = 'imp' THEN 1 END) AS click_through 
    from activity 
    group by appid 

演示:SQL Fiddle

如果使用MySQL,可以进一步简化为:

select appid 
     , SUM(type = 'click')*1.0 
     /SUM(type = 'imp') AS click_through 
    from activity 
    group by appid 
+0

对于这个例子,它工作正常,但现在想象你有没有印象的点击,你想删除它们,因为这很可能是错误。这个查询会忽略它。 – zipp 2017-03-31 17:59:42

+0

@zipp当然可以调整条件来处理额外的复杂性,例如,可以将整个事件包装在一个“CASE”表达式中,该表达式用于检查以确保展示次数高于点击次数。 – 2017-03-31 20:13:45

+0

我打开了一个单独的问题,以防万一您面临挑战: http:// stackoverflow。COM /问题/ 43148974/MySQL的,有条件自加盟 – zipp 2017-03-31 20:14:53

2

只是算子查询中的曝光和点击,并加入他们一起:

select appid, 
num_impressions, 
num_clicks, 
cast(num_clicks as float)/num_impressions as ctr 
from(
    select appid, count(1) as num_impressions 
    from activity 
    where type = 'imp' 
    group by appid 
)a 
join(
    select appid, count(1) as num_clicks 
    from activity 
    where type = 'click' 
    group by appid 
)b 
on (a.appid = b.appid); 

注意在ctrnum_clicks类型转换,以避免整数除法。

+1

我喜欢这是多么明确,它非常优雅。 – invoker 2015-02-24 18:50:06

+0

@harrisried:谢谢。 :)如果您发现答案有帮助,请考虑提供答案和/或接受答案(通过点击投票箭头下方左上角的复选标记)。 – 2015-02-24 19:01:52

+0

@harrisried:谢谢你的接受。我修正了一些小问题('ctr = clicks/impressions',而不是其他方法)。另外,您可能需要考虑将'join'转换为'left join',并将'cast(num_clicks as float)'替换为'cast(合并(num_clicks,0)为float)'来计算具有展示次数的应用没有点击(如果这适用于您的数据)。 – 2015-02-24 19:11:49

1

因为你是用两种不同的骨料使用不同的标准处理,您可以用子查询做到这一点:

SELECT d1.appid, (
    SELECT count(*) 
    FROM activity d2 
    WHERE d2.appid = d1.appid 
     d2.type = 'click' 
)/(
    SELECT count(*) 
    FROM activity d3 
    WHERE d3.appid = d1.appid 
     d3.type = 'imp' 
) AS click_through 
FROM activity d1; 
0
CREATE TABLE #activity 
(
    userid INT , 
    appid VARCHAR(1), 
    [type] VARCHAR(5) 
) 

INSERT INTO #activity 
VALUES 
(1,   'a' ,  'imp'), 
(2,   'a',  'imp'), 
(2,   'a',  'click'), 
(3,   'a',  'imp'), 
(4,   'a',  'imp'), 
(4,   'a',  'click'), 
(5,   'b',  'imp'), 
(5,   'b',  'click') 


SELECT A.appid, CAST(a.Clicks AS FLOAT)/B.Imp 
FROM 
( SELECT appid, COUNT(1) Clicks 
    FROM #activity 
    WHERE [type] ='CLICK' 
    GROUP BY appid 
) A 
INNER JOIN 
( SELECT appid, COUNT(1) Imp 
    FROM #activity 
    WHERE [type] ='imp' 
    GROUP BY appid 
) B ON A.appid = B.appid 

DROP TABLE #activity