我有一个MySQL数据库,其中一些表存储为innoDB类型。其中一个是work_session
,其结构是:
id
int(10)unsigned auto_increment primary project_id
int(10)unsigned index begin
datetime end
datetime 该表用于记录每个项目花费的时间。当然,每行end
都大于begin
。多行可能具有相同的project_id
,但具有相同begin
的行的end
和project_id
表示的间隔不会重叠。
我的目标是从此表中提取一些统计数据。特别是:
project_id
project_id
每天花费的时间
project_id
project_id
我能够使用PHP实现这一目标,但我想学习如何使用MySQL。
我能够通过
获得第一个统计数据SELECT
`project_id`,
SUM(`work_session_duration`) AS `project_duration`
FROM
(SELECT
`project_id`,
TIMESTAMPDIFF(SECOND, `begin`, `end`) AS `work_session_duration`
FROM `work_sessions`) AS `t1`
GROUP BY `project_id`
其他三个统计数据非常相似,特别是最后两个,但我无法通过MySQL找到解决方法。
答案 0 :(得分:1)
我认为每小时统计数据是最困难的部分。所以我只会为它提供一个解决方案。其他问题可以用类似的方式解决。
您需要一些帮助表:
calendar
| date |
|------------|
| 1970-01-01 |
| 1970-01-02 |
| ... |
| 1940-12-30 |
| 1940-12-31 |
hours
| hour |
|------|
| 0 |
| 1 |
| ... |
| 22 |
| 23 |
您可以在SO上找到许多答案,如何创建此类表格。我将跳过那一部分来保持我的答案紧凑。
使用帮助程序表,您可以在子查询中创建CROSS JOIN,其中包含数据所需的任何日期 - 小时组合。该子查询可以在重叠时与您的表连接。然后,您可以按project_id
和h.hour
进行分组,并计算工作时间总和:
select s.project_id, h.hour,
sum(timestampdiff(second, greatest(s.begin, h.begin), least(s.end, h.end))) as project_duration
from (
select h.hour,
timestamp(c.date, concat(h.hour, ':00:00')) as `begin`,
timestamp(c.date, concat(h.hour+1, ':00:00')) as `end`
from calendar c
cross join hours h
where c.date >= (select date(min(`begin`)) from work_sessions)
and c.date <= (select date(max(`end`)) from work_sessions)
) h
inner join work_sessions s
on s.begin < h.end
and s.end > h.begin
group by s.project_id, h.hour
答案 1 :(得分:0)
你尝试过这样的事吗?
SELECT
`project_id`,
SUM(`work_session_duration`) AS `project_duration`,
`days`
FROM
(SELECT
`project_id`,
TIMESTAMPDIFF(SECOND, `begin`, `end`) AS `work_session_duration`,
DATE_FORMAT(`begin`, '%Y-%m-%d') AS `days`
FROM `work_sessions`) AS `t1`
GROUP BY `project_id`, `days`
ORDER BY `days`
和
SELECT
`project_id`,
SUM(`work_session_duration`) AS `project_duration`,
HOUR(`begin`) AS `hours`
FROM
(SELECT
`project_id`,
TIMESTAMPDIFF(SECOND, `begin`, `end`) AS `work_session_duration`,
`begin`
FROM `work_sessions`) AS `t1`
GROUP BY `project_id`, `hours`
和
SELECT
`project_id`,
SUM(`work_session_duration`) AS `project_duration`,
WEEKDAY(`begin`) AS `weekdays`
FROM
(SELECT
`project_id`,
TIMESTAMPDIFF(SECOND, `begin`, `end`) AS `work_session_duration`,
`begin`
FROM `work_sessions`) AS `t1`
GROUP BY `project_id`, `weekdays`
或类似的东西......