MySQL - 计算 2 个最近记录之间的平均时间差
MySQL - Computing average time difference between 2 closest records
我有一个 table access
存储员工访问系统的时间以及他注销的时间。
access_id int(11) -- PK, auto-generated
employee_id (11)
in_time bigint(20)
out_time bigint(20)
我需要的是员工外出的平均时间(in_time - out_time员工上次访问的时间) - 所有员工.
到目前为止我管理的内容:
我可以使用这个(相当复杂的)查询设法计算单个员工的平均值
SELECT AVG (b.in_time - a.out_time) / 60000 AS avginminutes
FROM access a CROSS JOIN access b
WHERE
b.access_id =
(SELECT MIN(c.access_id)
FROM access c
WHERE c.access_id > a.access_id
and c.employee_id = 1765708 )
AND a.employee_id = 1765708
AND b.in_time - a.out_time != 0
ORDER BY a.access_id ASC;
我的主要问题是,如何修改此查询以计算所有员工的平均值?在花了很多时间之后,我没有得到任何结果。
其次(但不重要),有没有办法简化查询?
示例数据:
access_id|employee_id|in_time |out_time
|1 |1765708 |1643720400000|1643727600000
|2 |1765708 |1643728200000|1643734800000
|3 |1765708 |1643735100000|1643738400000
|4 |4344524 |1646125200000|1646128800000
|5 |4344524 |1646129100000|1646134200000
|6 |4344524 |1646134800000|1646142000000
|7 |4344524 |1646149200000|1646156400000
MySQL版本:5.5
(The average time when the employee was out)
=
(MAX(out_time) - MIN(in_time) - SUM(out_time - in_time)) / (COUNT(*) - 1)
即
SELECT employee_id,
(MAX(out_time) - MIN(in_time) - SUM(out_time - in_time)) / (COUNT(*) - 1) / 60000 avginminutes
FROM access
GROUP BY 1;
如果某个员工只有一行,当然会失败或产生 NULL(取决于 SQL 模式)。在严格模式下 - 根据 CASE 进行调整。
如果您使用的是 MySQL 8,则可以使用 LAG
函数查找每一行的上一个结束时间:
WITH cte AS (
SELECT
employee_id,
LAG(out_time) OVER (PARTITION BY employee_id ORDER BY in_time) AS prev_out,
in_time
FROM t
)
SELECT employee_id, AVG(in_time - prev_out)
FROM cte
GROUP BY employee_id
我有一个 table access
存储员工访问系统的时间以及他注销的时间。
access_id int(11) -- PK, auto-generated
employee_id (11)
in_time bigint(20)
out_time bigint(20)
我需要的是员工外出的平均时间(in_time - out_time员工上次访问的时间) - 所有员工.
到目前为止我管理的内容:
我可以使用这个(相当复杂的)查询设法计算单个员工的平均值
SELECT AVG (b.in_time - a.out_time) / 60000 AS avginminutes
FROM access a CROSS JOIN access b
WHERE
b.access_id =
(SELECT MIN(c.access_id)
FROM access c
WHERE c.access_id > a.access_id
and c.employee_id = 1765708 )
AND a.employee_id = 1765708
AND b.in_time - a.out_time != 0
ORDER BY a.access_id ASC;
我的主要问题是,如何修改此查询以计算所有员工的平均值?在花了很多时间之后,我没有得到任何结果。
其次(但不重要),有没有办法简化查询?
示例数据:
access_id|employee_id|in_time |out_time
|1 |1765708 |1643720400000|1643727600000
|2 |1765708 |1643728200000|1643734800000
|3 |1765708 |1643735100000|1643738400000
|4 |4344524 |1646125200000|1646128800000
|5 |4344524 |1646129100000|1646134200000
|6 |4344524 |1646134800000|1646142000000
|7 |4344524 |1646149200000|1646156400000
MySQL版本:5.5
(The average time when the employee was out)
=
(MAX(out_time) - MIN(in_time) - SUM(out_time - in_time)) / (COUNT(*) - 1)
即
SELECT employee_id,
(MAX(out_time) - MIN(in_time) - SUM(out_time - in_time)) / (COUNT(*) - 1) / 60000 avginminutes
FROM access
GROUP BY 1;
如果某个员工只有一行,当然会失败或产生 NULL(取决于 SQL 模式)。在严格模式下 - 根据 CASE 进行调整。
如果您使用的是 MySQL 8,则可以使用 LAG
函数查找每一行的上一个结束时间:
WITH cte AS (
SELECT
employee_id,
LAG(out_time) OVER (PARTITION BY employee_id ORDER BY in_time) AS prev_out,
in_time
FROM t
)
SELECT employee_id, AVG(in_time - prev_out)
FROM cte
GROUP BY employee_id