SELECT a.employee_id ,a.employee_name ,a.employee_salary ,b.department_idFROM ( SELECT * ,RANK() OVER (PARTITION BY department ORDER BY employee_salary DESC) AS ranking FROM employee ) AS aINNER JOIN department AS bON a.department = b.department_idWHERE a.ranking = 2; 题目2:网站登录时间间隔统计现有一张网站登录情况表login_info,该表记录了所有用户的网站登录信息,包含如下两个字段。
user_id(用户ID):VARCHAR。
login_time(用户登录日期):DATE。
login_info表的数据如下表所示。数据导入的代码如下:
DROP TABLE IF EXISTS login_info;CREATE TABLE login_info(user_id VARCHAR(8),login_time DATE)ENGINE = InnoDBDEFAULT CHARSET = utf8;INSERT INTOlogin_info (user_id,login_time) VALUE ('a001','2021-01-01'),('b001','2021-01-01'),('a001','2021-01-03'),('a001','2021-01-06'),('a001','2021-01-07'),('b001','2021-01-07'),('a001','2021-01-08'),('a001','2021-01-09'),('b001','2021-01-09'),('b001','2021-01-10'),('b001','2021-01-15'),('a001','2021-01-16'),('a001','2021-01-18'),('a001','2021-01-19'),('b001','2021-01-20'),('a001','2021-01-23');问题:计算每个用户登录日期间隔小于5天的次数。输出内容包括:
user_id(用户ID)
num(用户登录日期间隔小于5天的次数)
结果样例如下图所示。可供参考的解题思路:本题考查LEAD()函数在处理时间间隔问题上的使用方法,观察内层的查询部分,使用LEAD()函数在原有的login_time字段的基础上创造一列新的时间字段(即该用户下一次登录日期),内层查询代码如下:SELECT user_id
,login_time
,LEAD(login_time,1) OVER (PARTITION BY user_id ORDER BY login_time) AS next_login_time
FROM login_info;
查询结果如下图所示。 在上图中可以发现,经过LEAD()函数处理后,数据会根据user_id字段分组后按照login_time字段排序。经过内层的处理后,只需在外层筛选出next_login_time与login_time字段的日期差小于5天的数据,即最终统计的目标数据,这里使用了TIMESTAMPDIFF(DAY, login_time, next_login_time)计算日期差,最后分组聚合统计不同user_id的记录个数,即每个用户登录日期间隔小于5天的次数。涉及知识点:窗口函数、子查询、分组聚合、时间函数。本题的SQL代码如下,供读者参考:
SELECT a.user_id ,COUNT(*) AS numFROM ( SELECT user_id ,login_time ,LEAD(login_time,1) OVER (PARTITION BY user_id ORDER BY login_time) AS next_login_time FROM login_info) AS aWHERE TIMESTAMPDIFF(DAY, login_time, next_login_time) < 5 GROUP BY user_id;
DROP TABLE IF EXISTS purchase_channel;CREATE TABLE purchase_channel(user_id VARCHAR(8),channel VARCHAR(8),purchase_date DATE,purchase_amount INT(8))ENGINE = InnoDBDEFAULT CHARSET = utf8;INSERT INTOpurchase_channel (user_id,channel,purchase_date,purchase_amount) VALUE ('a001','app','2021-03-14',200) ,('a001','web','2021-03-14',100) ,('a002','app','2021-03-14',400) ,('a001','web','2021-03-15',3000) ,('a002','app','2021-03-15',900) ,('a003','app','2021-03-15',1000);
问题:查询每天仅使用手机端的用户、仅使用网页端的用户和同时使用网页端和手机端(both)的不同用户人数和总购物金额,并且即使某天某渠道没有用户的购买信息,也需要展示。输出内容包括:purchase_date(日期)channel(购买渠道)sum_amount(总购买金额)total_users(不同用户人数)结果样例如下图所示。可供参考的解题思路:根据用户ID和日期进行分组,通过统计用户在各购买渠道购物的记录个数来判断某用户在某日期购物时采用的访问方式(web、app和both)。其中,web和app可以通过一个SELECT语句查询,both则可以通过另一个SELECT语句查询。将两部分使用UNION连接在一起,并将以上部分作为子查询内部,在子查询外部统计不同购买日期、购买渠道的总购买金额和总购买用户。本部分SQL代码如下:
SELECT purchase_date ,channel ,SUM(sum_amount) sum_amount ,SUM(total_users) total_usersFROM ( SELECT purchase_date ,MIN(channel) channel ,SUM(purchase_amount) sum_amount ,COUNT(DISTINCT user_id) total_users FROM purchase_channel GROUP BY purchase_date ,user_id HAVING COUNT(DISTINCT channel) = 1 UNION SELECT purchase_date ,'both' channel ,SUM(purchase_amount) sum_amount ,COUNT(DISTINCT user_id) total_users FROM purchase_channel GROUP BY purchase_date ,user_id HAVING COUNT(DISTINCT channel) > 1 ) cGROUP BY purchase_date ,channel;
本部分输出结果如下图所示。上述部分似乎已经完成了本题要求,但仔细观察就会发现,题目要求即使某天某渠道没有用户的购买信息,也需要展示。而想要展示更全的信息,则考虑使用最全的信息(所有日期和3个渠道的笛卡尔积)与刚查询出的结果数据表进行LEFT JOIN连接,即可得到两张表根据日期和渠道进行连接的结果。涉及知识点:UNION、分组聚合、数据去重。本题的SQL代码如下,供读者参考:
SELECT t1.purchase_date ,t1.channel ,t2.sum_amount ,t2.total_usersFROM ( SELECT DISTINCT a.purchase_date ,b.channel FROM purchase_channel a, ( SELECT "app" AS channel UNION SELECT "web" AS channel UNION SELECT "both" AS channel ) b) t1LEFT JOIN (SELECT purchase_date,channel,SUM(sum_amount) sum_amount,SUM(total_users) total_usersFROM (SELECT purchase_date ,MIN(channel) channel ,SUM(purchase_amount) sum_amount ,COUNT(DISTINCT user_id) total_users FROM purchase_channel GROUP BY purchase_date,user_id HAVING COUNT(DISTINCT channel) = 1 UNION SELECT purchase_date ,'both' channel ,SUM(purchase_amount) sum_amount ,COUNT(DISTINCT user_id) total_users FROM purchase_channel GROUP BY purchase_date,user_id HAVING COUNT(DISTINCT channel) > 1)c GROUP BY purchase_date, channel) t2ON t1.purchase_date = t2.purchase_date AND t1.channel = t2.chan[/url]