【问题标题】:How to group data in MySQL for every 3 hours from today?如何从今天起每 3 小时对 MySQL 中的数据进行分组?
【发布时间】:2014-08-24 15:34:40
【问题描述】:

我想为我的一个图表检索数据,并且想为它想出一个简单的解决方案,而不是执行 8 个子查询。

users 表如下所示:

user_id
1
2
3
4
5

pts 表如下所示:

id  user_id  status  points                 time
1         1       0      100  2014-08-23 03:34:54
2         4       0      100  2014-08-23 04:04:44
3         1       1      300  2014-08-23 08:34:21
4         1       0      300  2014-08-23 15:25:11
5         1       0      200  2014-08-23 22:23:12

查询看起来像这样(有几个 cmets,我不知道该放什么):

    "SELECT  *,
        (
            SELECT  SUM(points)
            FROM    pts
            WHERE   status = 0 
            AND     user_id = 1
            AND     time >= "THIS DAY'S 00:00" AND <= "THIS DAY'S 03:00" 
        ),
        (
            SELECT  SUM(points)
            FROM    pts
            WHERE   status = 0 
            AND     user_id = 1
            AND     time >= "THIS DAY'S 03:00" AND <= "THIS DAY'S 06:00"
        ),
        (
            SELECT  SUM(points)
            FROM    pts
            WHERE   status = 0
            AND     user_id = 1 
            AND     time >= "THIS DAY'S 06:00" AND <= "THIS DAY'S 09:00"
        ),
        (
            SELECT  SUM(points)
            FROM    pts
            WHERE   status = 0 
            AND     user_id = 1
            AND     time >= "THIS DAY'S 12:00" AND <= "THIS DAY'S 15:00"
        ),
"ETC......"
FROM    pts
WHERE   user_id = 1
AND     status  = 1
"

所以基本上查询需要在当天每 3 小时从数据库中收集一次数据(所以如果我使用上述选项,它将是 8 个子查询)。此外,如果间隔内尚未达到当前时间,则查询应返回 0 / null。如果当前时间在其中一个区间内,则它应该返回从区间开始到区间结束的数据。

我想要达到的结果:

id  user_id  points                                       time
1         1       0  2014-08-23 00:00:00 - 2014-08-23 03:00:00
2         1     200  2014-08-23 03:00:00 - 2014-08-23 06:00:00
3         1     300  2014-08-23 06:00:00 - 2014-08-23 09:00:00
4         1       0  2014-08-23 09:00:00 - 2014-08-23 12:00:00
5         1       0  2014-08-23 12:00:00 - 2014-08-23 15:00:00
6         1     300  2014-08-23 15:00:00 - 2014-08-23 18:00:00
7         1       0  2014-08-23 18:00:00 - 2014-08-23 21:00:00
8         1     200  2014-08-23 21:00:00 - 2014-08-23 00:00:00

这可以用 MySQL 实现吗?

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    你可以只对小时使用聚合和算术:

    select floor(hour(time) / 3) as hourgroup, sum(points)
    from pts
    where status = 0 and user_id = 1 and
          date(time) = "THIS DAY"
    group by floor(hour(time) / 3);
    

    对于您的特定输出:

    select (hour(time) div 3) as id, user_id, sum(points),
           date('2014-08-23') + interval 3 * (hour(time) div 3) hour as starttime,
           date('2014-08-23') + interval 3 * ((hour(time) div 3) + 1) hour as endtime
    from pts
    where status = 0 and user_id = 1 and
          date(time) = date('2014-08-23')
    group by floor(hour(time) / 3);
    

    计数为零的值存在问题。我不确定这些有多重要。您的查询对数据进行了透视,但您想要的结果并未进行透视。

    编辑:

    如果你真的需要所有组的时间,你可以这样做:

    select n.n as id, user_id, sum(points),
           date('2014-08-23') + interval 3 * n.n hour as starttime,
           date('2014-08-23') + interval 3 * (n.n + 1) hour as endtime
    from (select 0 as n union all select 1 union all select 2 union all select 3 union all
          select 4 union all select 5 union all select 6 union all select 7
         ) n left join
         pts
         on n.n = hour(time) div 3
    where status = 0 and user_id = 1 and
          date(time) = date('2014-08-23')
    group by n.n;
    

    【讨论】:

    • (+1)另一种方法是 DIV 运算符。
    • 感谢您的回答。它工作得很好,除了你提到的。没有结果时不显示查询。不过那会很棒。有没有办法解决这个问题?
    • 您编辑的答案基本上给出了完全相同的结果,而不是更简单的答案。我在这里错过了什么吗?
    猜你喜欢
    • 2021-07-25
    • 2012-03-18
    • 2020-05-15
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    相关资源
    最近更新 更多