MySQL条件自连接

时间:2017-03-31 20:12:56

标签: mysql sql

CREATE TABLE dialoglog (
   userid int,
   appid int,
   type varchar(100) ,
   ds timestamp
 );

数据

userid  appid   type    ds
1        1      imp     January, 19 2016 03:14:07
1        1      click   January, 20 2016 03:14:07
2        1      imp     January, 19 2016 03:14:07
2        1      click   January, 18 2016 03:14:07
3        6       imp    January, 19 2016 03:14:07
10       1      click   January, 19 2016 03:14:07
1        1       imp    January, 20 2016 03:12:07

问题

每个appid的点击率(点击次数/点击率)是多少?

问题

我们要打印每组的点击率

问题是我们有“坏”数据:

  • 用户10点击appid 1,但对appid 1 =>没有任何印象我们应该忽略它
  • 用户2在appid 1 =>之前点击appid 1我们应该忽略它

因此,这样的查询:

SELECT SUM(CASE WHEN type='click' THEN 1 else 0 END)*1.0/SUM(CASE WHEN dialoglog.type='imp' THEN 1 else 0 END) as ctr,appid 
     FROM  dialoglog GROUP BY  appid;

由于我刚才所说的约束而行不通。     是否可以在单个mysql查询中编写所有这些约束?

以下sqlfiddle可以使用

预期结果

对于appid 1,我们有3次展示和1次点击(这是有效的,因为用户2时间戳点击< timestamp展示,对于用户10没有印象)因此我们应该有1/3的点击率。

对于appid 6,我们只有一次展示=> CTR = 0

因此我期待这个结果:

appid  CTR
1      0.333
6      0

到目前为止我尝试了什么

我考虑过做左连接,但问题是它会复制右表:

SELECT * FROM dialoglog t1 LEFT JOIN dialoglog t2 on t1.userid=t2.userid and t1.appid=t2.appid and t1.type<>t2.type WHERE t1.type="imp" and t1.ds<t2.ds;



userid  appid   type    ds                   userid appid   type    ds
1        1      imp January, 19 2016 03:14:07   1    1    click January, 20 2016 03:14:07
1        1      imp January, 19 2016 03:12:07   1    1    click January, 20 2016 03:14:07

1 个答案:

答案 0 :(得分:1)

您似乎需要为每个用户提供最早的“imp”。然后,您可以在该时间点之后按交易进行汇总:

SELECT dl.appid, SUM(dl.type = 'click') / SUM(dl.type = 'imp')
FROM dialoglog dl LEFT JOIN
     (SELECT dl2.userId, MIN(ds) as imp_ds
      FROM dialoglog dl2
      WHERE type = 'imp'
      GROUP BY dl2.userid
     ) dlimp
     ON dl.userid = dlimp.userid 
WHERE dl.ds >= dlimp.imp_ds
GROUP BY dl.appid;