我有一张桌子,所有用户都会登录。 我想运行一个查询,该查询将提取每个用户登录的次数,但如果用户每天登录超过4次,则将其限制为4。 然后做一笔总和以获得登录总数。 除此之外,我想撤回登录总数的时间范围。因此,我将登录总数指定为100,然后查询必须撤回最早的日期,从今天起返回并计算每个用户的登录次数(限制为4,如果大于4)。
我的查询到目前为止,每个用户的总计列表限制为4个:
SELECT (case when (count(l.user_id) > 4) then 4 else count(l.user_id) end) as cappedcount
FROM `logins` l
where l.store_id = 908
and l.login_dt > '2018-04-17 00:00:00' and l.login_dt < '2018-04-18 23:59:59'
group by l.user_id order by cappedcount desc
我目前正在指定日期范围,但不想在最终查询中执行此操作。
答案 0 :(得分:0)
如果我理解正确,您只想查看每个用户和每天的最后四次登录,并忽略他们之前的登录。从这个集合你想要最后100次登录。
因此,第一项任务是获得每个用户和每天的最后四次登录,这通常可以通过窗口函数来解决,但MySQL并没有使用它们。因此,请计入子查询(可能需要很长时间):
select *
from logins
where
(
select count(*)
from logins later
where later.user_id = logins.user_id
and date(later.login_dt) = date(logins.login_dt)
and later.login_dt > logins.login_dt
) < 4
order by login_dt desc
limit 100;
我建议为此查询提供以下索引:
create index idx_logins on logins (user_id, login_dt);
答案 1 :(得分:0)
您使用的MySQL版本是什么?因为据我所知with clause
仅在最新版本的MySQL中受支持。
我相信你的第一个请求的答案是:
select sum(cntx) from (
select user_id, date(login_time), least(count(*), 4) cntx
from logins
where login_time between '2018-04-10 00:00:00' and '2018-04-17 00:00:00'
group by user_id, date(login_time)
) x
,您可以在sqlfiddle.com中查看。
对于你的第二个问题,我有以下答案,我相信这不是最好的解决方案,但它适用于MySQL 5.6。在下一个MySQL版本(MySQL 8)中,您可以使用with子句为此问题提供更好的解决方案。我在解决方案中使用视图来跳过重复的查询:
create view xlogins as
select user_id, date(login_time) xdt, least(count(*), 4) xcnt
from logins
group by user_id, date(login_time);
create view xxlogins as
select distinct xdt, (select sum(x2.xcnt)
from xlogins x2
where x2.xdt >= x1.xdt) sumx
from xlogins x1;
select min(x1.xdt)
from xxlogins x1
join xxlogins x2 on x1.xdt < x2.xd
where x1.sumx >= 100
and x2.sumx <= 100
在此sqlfiddle.com中找到解决方案,我刚刚将100更改为10。