SQL 按行划分数据

SQL divide data in rows

我有以下 table 名为

Table: activity

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

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

只需计算子查询中的展示次数和点击次数并将它们合并在一起:

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 的类型转换以避免整数除法。

您可以使用子查询执行此操作,因为您正在使用不同的条件处理两个不同的聚合:

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;

您可以使用条件聚合来执行此操作:

   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
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