mysql - 这可以用mysql吗?

标签 mysql

首先:对标题感到抱歉,但也许我以后会找到更好的。

几分钟前我问过这个问题,但由于我无法描述我想要的东西,所以我再试了一次:)

这是我的表结构: http://sqlfiddle.com/#!2/b25f9/37

该表用于存储用户 session 。

除此之外,我想生成一个堆叠条形图,显示我有多少活跃用户。我的想法是,我像这样根据用户最近几天的在线时间对用户进行分组 enter image description here

假设是星期五:

  • B 组:周四(和今天)在线的用户
  • C 组:星期四但星期三(和今天)不在线的用户
  • D 组:周四或周三不在线但周二(和今天)在线的用户
  • E 组:周四、周三或周二未在线但上周一、周日或周六(以及今天)的用户
  • A 组:与其他组不匹配(但仅在今天)的用户

  • 我只想知道这些组中的用户数量(特定日期)

  • 一个用户只能属于这些组之一(在同一天)

最佳答案

另一个更新:不小心(通过复制和粘贴)有 starttime = ... 或 starttime = ... 但它应该是 starttime = ... 或结束时间 = ...

更新:

更详细地解释我的查询(在最终查询中有更多评论):

首先我们得到了

SELECT
...
FROM gc_sessions s
WHERE DATE(starttime) = CURDATE() OR DATE(endtime) = CURDATE()

这无异于说“给我 session 今天开始或今天结束的所有用户”。不得不一次又一次地考虑这两次使得查询有点笨拙,但实际上并没有那么复杂。

所以,通常我们会使用 COUNT() 函数来计算某些东西,显然,但由于我们想要“条件计数”,我们只需使用 SUM() 函数并告诉它何时加 1 以及何时不加 1。

SUM (CASE WHEN ... THEN 1 ELSE 0 END) AS a_column_name

SUM() 函数现在检查今天 session 结果集中的每一行。因此,对于此结果集中的每个用户,我们都会查看该用户是否在我们指定的日期在线。他/她在线多少次并不重要,因此出于性能原因,我们使用 EXISTS。使用 EXISTS,您可以指定一个子查询,该子查询在找到某些内容后立即停止,因此只要它不是 NULL,它返回什么并不重要。 .所以不要对我选择 1 的原因感到困惑。在子查询中,我们必须将当前从外部查询检查的用户与来自内部查询(子查询)的用户连接起来,并指定时间窗口。如果所有条件都满足计数 1,否则计数 0,如前所述。

SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterday,

然后我们为每个条件创建一列,瞧,您在一个查询中就拥有了所有需要的东西。因此,随着您更新的问题,您的标准发生了变化,我们只需要添加更多规则:

SELECT
/*this is like before*/
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS FridayAndThursday,
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 2 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 2 DAY)))
         /*this one here is a new addition, since you don't want to count the users that were online yesterday*/
         AND NOT EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY)))
    THEN 1 ELSE 0 END) AS FridayAndWednesdayButNotThursday,
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 3 DAY) /* minus 3 days to get tuesday*/
                       OR (date(endtime) = CURDATE() - INTERVAL 3 DAY)))
         /*this is the same as before, we check again that the user was not online between today and tuesday, but this time we really use BETWEEN for convenience*/
         AND NOT EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY)))
    THEN 1 ELSE 0 END) AS FridayAndTuesdayButNotThursdayAndNotWednesday,
.../*and so on*/
FROM gc_sessions s
WHERE DATE(starttime) = CURDATE() OR DATE(endtime) = CURDATE()

那么,我希望你现在明白了。还有问题吗?随意问。

更新结束

上一版问题的答案:

select 
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterday,
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterdayOrTheDayBeforeYesterday,
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndWithinTheLastWeek
from gc_sessions s
where date(starttime) = CURDATE()
or date(endtime) = CURDATE()

关于mysql - 这可以用mysql吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14561430/

相关文章:

mysql - AWS RDS MYSQL SSL 如何工作?

MySQL 工作台错误 1064

android - 向数据库中插入数据时 logcat 出错

mysql - 建立数据集市您每年使用一张表吗?数据库

mysql - 在 MySql/parent-child 关系中链接不同表中的列

mysql - 调用先前 mysql 查询的值

php - 动态 PHP/MySQL 上传表单

mysql - 选择字符串中包含附近单词的记录

java - 如何将 SQL 表创建转换为 JPA hibernate 自动创建

jquery - 如何执行实时查询并以自动完成方式显示数据