我在mysql(v5.7)中有一个记录用户请求的日志表,从中我提取了一个活动细分表,显示每个月的用户数和总点击率,例如:
Date Users Hits
September 2018 20 1,839
August 2018 23 2,723
July 2018 21 1,632
June 2018 22 2,981
这是目前通过以下查询实现的:
SELECT month(l.time) m, year(l.time) y, date_format(l.time, '%M %Y') monthyear,
(select count(distinct userid) from log lm
where month(lm.time) = month(l.time) and year(lm.time) = year(l.time)) users,
count(u.name) hits
FROM log l left join users u on u.id=l.userid
group by date_format(l.time, '%M %Y')
order by l.time desc, l.id desc
此sql失败,只启用了\u full \u group \u by,这是mysql中的默认值,因为并非所有表达式都在GROUPBY子句中。我发现的解决方案通常涉及使用聚合函数(如max())或将所有表达式添加到GROUPBY子句中,但是'users'子查询使这些方法成了问题:我不能使用max()方法(无效语法),将其添加到groupby子句会导致查询非常慢,以至于我还没有看到测试完成。
我觉得可能有一种解决方案既优雅又高效,而不必仅禁用“完全分组”,但我对sql的了解还不够深入。
2条答案
按热度按时间kse8i1jr1#
下面是一个简化的查询:
您不需要选择列表中的月份或年份,因为您没有在所需的结果中显示它。
你不需要加入
users
表,除非您的意思是只计算具有非nullname
列(count)忽略空值,我猜您的意思是计算日志中的所有命中数,这意味着您应该使用COUNT(*)
而不是COUNT(u.name)
.我删除了orderby子句,因为它引用了结果中不存在的列。如果要按月份排序,则应考虑按所需的排序方式格式化月份:
默认情况下,groupby将按值对组进行排序。
lp0sw83n2#
我不知道您为什么要对此使用子查询。这不是你想要的吗?