有一位学生在找数据分析工作的时候,遇到一个笔试题,内容如下: 现有注册用户表table_user,有两个字段: user_id(用户id)、reg_tm(注册时间)。 有订单表table_order,有三个字段: order_id(订单号)、order_tm(下单时间)、user_id(用户id)。 查询2019年1月1日至今,每天的注册用户数,下单用户数,以及注册当天即下单的用户数(请尽量在一个sql语句中实现)。
题意分析:
综合以上分析,得到解题思路:
1、将注册表的注册时间和订单表的下单时间做纵向链接,生成一个临时表,只有一个字段 reg_tm:
select reg_tm from table_user union select order_tm from table_order
2、再用上表和注册表及订单表做左连接:
select * from( select reg_tm from table_user union select order_tm from table_order) astable_date left join table_user ontable_date.reg_tm=table_user.reg_tm left join table_order ontable_date.reg_tm=table_order.order_tm;
3、题目要求查询2019年1月1日至今的数据情况,把这个条件加在where后面:
select * from( select reg_tm from table_user union select order_tm from table_order) astable_date left join table_user ontable_date.reg_tm=table_user.reg_tm left join table_order on table_date.reg_tm=table_order.order_tm wheretable_date.reg_tm>="2019-01-01";
4、题目是查看每天的注册用户数,下单用户数,以及注册当天即下单的用户数; 需要对日期进行分组,注册用户数是对注册表的user_id进行计数,下单用户数是对订单表的user_id进行计数,注册当天即下单的用户数是对注册表的注册时间与订单表的注册时间相等的user_id进行计数。 需要注意的是,在将临时表table_date与table_user左连时,对应关系是一对多,生成的结果是一个多表,再与table_order左连,对应关系是多对多,多对多的情况下,数据一定是有重复的,所以需要去重处理(distinct函数)。 另外把没有结果的null替换成0(ifnull函数),最终代码如下:
selecttable_date.reg_tm,ifnull(count(distinct table_user.user_id),0) 注册用户数, ifnull(count(distinct table_order.user_id),0) 下单用户数, ifnull(count(distinct if(table_user.reg_time=table_order.order_timeand table_user.user_id=table_order.user_id,table_user.user_id,null)),0) 下单用户数 from( select reg_tm from table_user union select order_tm from table_order) astable_date left join table_user on table_date.reg_tm=table_user.reg_tm left join table_order ontable_date.reg_tm=table_order.order_tm wheretable_date.reg_tm>="2019-01-01" group by table_date.reg_tm;
题目是没有数据的,如果直接看看不懂的话,可以自己先构造一个数据,再尝试文中的代码,一步一步理解。