1.题意

  • 计算每个周对应所有用户的平均登陆次数,结果按照每周周一升序排序,次数保留两位小数
  • 从描述可知,我们需要的登录次数是以每周为基准来计算的,所以需要先按照每周进行分组后,才能进行计算;需要注意的是,题目中说“用户可能在一天内登录多次”,所以我们在计算的时候还需要对同一个用户的多次登录行为进行去重

2.思路

  • 从题目的输出来看,我们需要获取每周的周一才行;也就是说:我们需要获取每个日期对应当前星期的周一日期。
  • 从这个问题出发,有一个思路可以借鉴,即当前日期 - 当前日期对应的星期数 + 1,了解了这个思路后,我们要做的就是想办法获取当前日期对应的星期数了刚好,MySQL中有一个名为"WEEKDAY()"的函数就有这样的功能,不过需要注意的是,该函数的返回值是星期数 - 1 MySQL官方文档:https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekday
  • 了解了这个函数后,我们就能够通过"当前日期 - WEEKDAY(当前日期)"获取当前星期的星期一对应的日期了计算平均登录次数的时候,无非就是总次数 / 用户数。不过需要注意的是用户数必须先去重(例如使用DISTINCT),而且计算的每个星期的数据,所以需要根据我们之前获取的星期一日期进行分组(使用GROUP BY)而保留两位小数的要求则可以通过ROUND函数满足,最后别忘了排序综上,不难写出以下SQL:
SELECT 
	login_date - WEEKDAY(login_date) AS 'week_begin',
	ROUND(COUNT(*) / COUNT(DISTINCT uid), 2) AS 'avg_times' 
FROM 
	user_login_tb
GROUP BY week_begin
ORDER BY week_begin
  • 但是这样写之后,提交时发现和示例结果不匹配,这是因为我们直接用日期值与一个数字进行了运算,此时日期值会变为常规的数字后再进行运算,这样计算的结果往往不是我们想要的,而且也不再是日期格式了: alt

  • 为了解决日期值和数字之间计算的问题,我们需要使用专用的日期计算函数"DATE_SUB()",该函数有一些特殊的语法,详情参考官方文档: https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-sub 此时SQL修改为:

SELECT
	DATE_SUB(login_date, INTERVAL WEEKDAY(login_date) DAY) AS 'week_begin',
	ROUND(COUNT(*) / COUNT(DISTINCT uid), 2) AS 'avg_times'
FROM
	user_login_tb
GROUP BY week_begin
ORDER BY week_begin