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是userid,我想获得每个月(所有应用程序)的session_time总数(总和),过去6个月按月计算。
如果一个月内多次使用某个应用(基于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小提琴:http://sqlfiddle.com/#!2/4eaf2
谢谢你,
窗扇
答案 0 :(得分: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
答案 1 :(得分: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
答案 2 :(得分:1)
虽然我在获取6个月的记录时遇到了问题,但我会在其他计算机上完成但在当前计算机上没有MySQL。我从Kickstart那里抓了那部分(因为他的功劳)。
无论如何,我从6个月前和现在的12个用户开始,最内层的“PreQuery”(别名PQ)。确保我不仅仅是从今天起6个月(月2日) ,或者即使在本月26日运行,但想要6个月前的第一个,我做了一些日期数学,直到6个月前的最后一天,然后在下个月的第一天增加1天。所以这将创建
10月2日 - 6个月= 4月2日...然后移动到4月30日的最后一天,然后加1天到5月1日。所以,现在5月1日到10月当前,10月是第6个月,如果1天到整个月。如果你想从4月1日到现在,那么请回到7个月。
因此,我得到每个应用,用户,每月和每个月的最大实例。我包括用户,以防你想要所有用户,而不是将来只有一个用户。
一旦查询每个应用/用户/月的MAX(),我就会再次加入会话,但仅限于那些匹配的会话。
最后通过左连接应用到外部月份列表中,您可以完成其余的工作。同样,如果您想要所有用户,您只需将用户添加到外部查询和分组依据。
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
答案 3 :(得分: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
和userid
显示任何月份的最新appid
。请注意,调用此字段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;
答案 4 :(得分:0)
如果我理解你的问题是正确的,那么这应该是你的查询(当前日期的IBM DB2语法):
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(当前日期)功能来比较自0年以来的日期。