0

enter code here我有一个结构如下的表:

| ID (bigint) | APPID (Bigint)| USAGE_START_TIME (datetime) | SESSION_TIME (bigint) |  USERID (bigint)   |
-----------------------------------------------------------------------------------------------------------
|  1          |        1      |         2013-05-03 04:42:55 |       400             |       12           |
|  2          |        1      |         2013-05-12 06:22:45 |       200             |       12           |
|  3          |        2      |         2013-06-12 08:44:24 |       350             |       12           |
|  4          |        2      |         2013-06-24 04:20:56 |         2             |       12           |
|  5          |        3      |         2013-06-26 08:20:26 |         4             |       12           |
|  6          |        4      |         2013-09-12 05:48:27 |        50             |       12           |

现在,如果 put 是用户 ID,我想获得过去 6 个月每月(所有应用程序)的总(总和)session_time。

如果一个应用程序在一个月内使用超过一次(基于usage_start_time),则只有最新的session_time 应该包含在该应用程序的总和中。

对于上面的例子,结果应该是这样的(如果当前月份是 10 月,并且输入是 userid=13):

| MONTH       | TOTAL_SESSION_TIME | 
------------------------------------
|  10         |        0           |            
|   9         |       50           |         
|   8         |        0           |         
|   7         |        0           |         
|   6         |        6           | 
|   5         |      200           |

这里月份以数字形式表示月份(例如:10 表示 10 月)。

目前我每个月都使用单独的查询。例如:

SELECT 
COALESCE(SUM(failcount),0) AS TOTAL_SESSION_TIME , MONTH(CURRENT_DATE) AS MONTH 
FROM appstime 
WHERE MONTH(`USAGE_START_TIME`) = MONTH(CURRENT_DATE) AND userid=12

但这并没有给我预期的结果。

另外,我想知道我是否可以使用单个查询而不是每个月的查询来执行此操作。我正在使用 PHP+Mysql。

请在此处查看 sql fiddlehttp ://sqlfiddle.com/#!2/4eaf2

谢谢你,
萨什

4

5 回答 5

1

虽然我在获取 6 个月的记录时遇到了问题,但我会在我的另一台机器上完成,但当前机器上没有 MySQL。我从 Kickstart 上刮掉了那部分(为了他的功劳)。

无论如何,我从 6 个月前的当前用户和 12 的当前用户开始,从最里面的“PreQuery”(别名 PQ)开始。为了确保我不只是从今天(月 2 日)开始获得 6 个月,甚至如果在本月 26 日运行,但想要 6 个月前的第一个,我通过转到 6 个月前的最后一天做了一些日期数学,然后添加 1 天作为下个月的第一天。所以这将创建

10 月 2 日 - 6 个月 = 4 月 2 日...然后移动到 4 月 30 日的最后一天,然后添加 1 天到 5 月 1 日。所以,现在 May1 到 10 月当前,其中 10 月是第 6 个月,如果 1 天到整个月。如果您想从 4 月 1 日到现在,请返回 7 个月。

因此,我每月获取每个应用程序、用户和每个月的最大实例。我将用户包括在内,以防您将来想要所有用户,而不仅仅是一个用户。

一旦查询了每个应用程序/用户/月的 MAX(),我就会再次加入会话,但仅适用于匹配的会话。

最后通过左连接应用到外部月份列表中,剩下的就给你了。同样,如果您想要所有用户,您可以将用户添加到外部查询和 group by 子句。

SELECT
      AllMonths.aMonth,
      COALESCE( SUM( Ap2.Session_Time ), 0 ) as Total_Session_Time
   from
      ( SELECT MONTH(DATE_ADD(NOW(), INTERVAL aInt MONTH)) AS aMonth
           FROM
            (
                SELECT 0 AS aInt 
                    UNION SELECT -1 
                    UNION SELECT -2 
                    UNION SELECT -3 
                    UNION SELECT -4 
                    UNION SELECT -5
            ) aCnt ) AllMonths
      LEFT JOIN
         ( select
                 appstime.AppID,
                 appstime.UserID,
                 MONTH( appstime.Usage_Start_Time ) as PerMonth,
                 MAX( appstime.Usage_Start_Time ) as ThisTime
              from 
                 ( select @StartDate := last_day( now() - interval 6 month ) + interval 1 day ) sqlvars,
                 appstime
              where
                     appstime.Usage_Start_Time >= @StartDate
                 AND appstime.UserID = 12
              group by
                 appstime.AppID,
                 appstime.UserID,
                 MONTH( appstime.Usage_Start_Time ) ) PQ
         ON AllMonths.aMonth = PQ.PerMonth
         LEFT JOIN appstime Ap2
             ON PQ.AppID = Ap2.AppID
            AND PQ.UserID = Ap2.UserID
            AND PQ.ThisTime = Ap2.Usage_Start_Time
   group by         
      AllMonths.aMonth
于 2013-10-02T12:40:58.747 回答
1

你想要吗GROUP BY

SELECT 
SUM(COALESCE(SESSION_TIME,0)) AS TOTAL_SESSION_TIME , 
MONTH(USAGE_START_TIME) AS THE_MONTH 
FROM appstime 
WHERE userid=13 AND 
DATE(SESSION_TIME) > DATE_SUB(NOW(), INTERVAL 6 MONTH)
GROUP BY THE_MONTH

更新:

这会将结果限制为每个 appid 每月的最大日期:

SELECT 
SUM(COALESCE(session_time,0)) AS TOTAL_SESSION_TIME , 
MONTH(usage_start_time) AS THE_MONTH 
FROM appstime 
INNER JOIN
    (
    SELECT appid , MAX(usage_start_time) AS max_app_date
    FROM appstime
    GROUP BY appid
    ) grouped_apps ON 
      grouped_apps.appid = appstime.appid AND
      grouped_apps.max_app_date = appstime.usage_start_time
WHERE userid=12 
GROUP BY THE_MONTH
于 2013-10-02T11:21:16.287 回答
1

未经测试,但类似这样:-

SELECT ForMonths.aMonth, IFNULL(SUM(SESSION_TIME), 0)
FROM
(
    SELECT MONTH(DATE_ADD(NOW(), INTERVAL aInt MONTH)) AS aMonth
    FROM
    (
        SELECT 0 AS aInt UNION SELECT -1 UNION SELECT -2 UNION SELECT -3 UNION SELECT -4 UNION SELECT -5
    ) aCnt
) ForMonths
LEFT OUTER JOIN 
(
    SELECT a.USERID, a.APPID, aMonth, SESSION_TIME
    FROM appstime a
    INNER JOIN
    (
        SELECT USERID, APPID, MONTH(USAGE_START_TIME) AS aMonth, MAX(USAGE_START_TIME) AS USAGE_START_TIME
        FROM appstime
        GROUP BY USERID, APPID, aMonth
    ) b
    ON a.USERID = b.USERID
    AND a.USAGE_START_TIME = b.USAGE_START_TIME
    AND a.APPID = b.APPID
  WHERE a.USERID = 12
) ForDetails
ON ForMonths.aMonth = ForDetails.aMonth
GROUP BY ForMonths.aMonth

可以简化,但是一个子查询可以获取过去 6 个月的每个月,并将其与另一个子查询相结合,以获取用户每个月的最新金额。

编辑 - 使用年份和月份: -

SELECT ForMonths.aMonth, IFNULL(SUM(SESSION_TIME), 0)
FROM
(
    SELECT EXTRACT(YEAR_MONTH FROM DATE_ADD(NOW(), INTERVAL aInt MONTH)) AS aMonth
    FROM
    (
        SELECT 0 AS aInt UNION SELECT -1 UNION SELECT -2 UNION SELECT -3 UNION SELECT -4 UNION SELECT -5
    ) aCnt
) ForMonths
LEFT OUTER JOIN 
(
    SELECT a.USERID, a.APPID, aMonth, SESSION_TIME
    FROM appstime a
    INNER JOIN
    (
        SELECT USERID, APPID, EXTRACT(YEAR_MONTH FROM USAGE_START_TIME) AS aMonth, MAX(USAGE_START_TIME) AS USAGE_START_TIME
        FROM appstime
        GROUP BY USERID, APPID, aMonth
    ) b
    ON a.USERID = b.USERID
    AND a.USAGE_START_TIME = b.USAGE_START_TIME
    AND a.APPID = b.APPID
  WHERE a.USERID = 12
) ForDetails
ON ForMonths.aMonth = ForDetails.aMonth
GROUP BY ForMonths.aMonth
ORDER BY ForMonths.aMonth
于 2013-10-02T11:33:17.873 回答
0

如果我正确理解了您的问题,那么这应该是您的查询(IBM DB2 Syntax for current date):

SELECT MONTH(USAGE_START_TIME) AS MONTH, SESSION_TIME as TOTAL_SESSION_TIME
FROM appstime
WHERE (MONTH(CURRENT DATE) - MONTH(USAGE_START_TIME)) BETWEEN 0 AND 6
GROUP BY MONTH(USAGE_START_TIME)
HAVING SUM(SESSION_TIME)

这会计算过去 6 个月以来每月的所有会话时间。

干杯。

编辑:这会在当月从同一个应用程序获取所有应用程序调用。要从同一应用程序 ID 获取最后一次调用,您需要一个存储过程来执行此操作。每个月有 6 个变量,如果日期大于同月的最后一个,则在选择循环中检查。我建议您对 MySQL 使用等效的 DAYS(current date) 函数来比较自 0 年以来的日期(以天为单位)。

于 2013-10-02T11:25:59.707 回答
0

您需要使用聚合函数(即group by):

select   userid,
         month(usage_start_time) as month,
         sum(session_time) as total_session_time
from     appstime
group by userid,
         month(usage_start_time);

编辑session_time只显示任何一个月中最近的,按useridappid。请注意,调用此字段total_session_time可能不是一个好主意!

select    latest.userid,
          latest.appid,
          month(latest.usage_start_time) as month,
          latest.session_time as latest_session_time

from      appstime as latest

left join appstime as later
on        later.userid           = latest.userid
and       later.appid            = latest.appid
and       later.usage_start_time > latest.usage_start_time

where     later.id is null;
于 2013-10-02T11:21:16.787 回答