MySql Count of Count If

时间:2018-04-19 11:15:58

标签: mysql sql

我有一张桌子,所有用户都会登录。 我想运行一个查询,该查询将提取每个用户登录的次数,但如果用户每天登录超过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

我目前正在指定日期范围,但不想在最终查询中执行此操作。

2 个答案:

答案 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。