我需要做的是返回每天的覆盖范围(操作员在现场的小时数)。面临的挑战是,我需要忽略覆盖范围上的差距,而不能重复计算两个操作员同时登录的小时数。例如,下图是表格的直观表示。
图像的逻辑如下:
因此,没有重叠的总覆盖时间为6小时,我需要查询产生的值。到目前为止,我可以忽略重复计数,方法是将每天的最小日期中的最大值减去两个值:
SELECT YEAR, WEEK, SUM(HOURS)
FROM
(SELECT
YEAR(SignedIn) AS YEAR,
WEEK(SignedIn) AS WEEK,
DAY(SignedIn) AS DAY,
time_to_sec(timediff(MAX(SignedOut), MIN(SignedIn)))/ 3600 AS HOURS
FROM OperatorLogs
GROUP BY YEAR, WEEK, DAY) As VirtualTable
GROUP BY YEAR, WEEK
之所以产生7,是因为它需要首次登录(上午10点)并计算直到最后一次退出(下午4:00)为止的小时数。但是,它包括覆盖范围(12-1)中的缺口,不应包括在内。我不确定如何从总时数中删除该时间,同时在出现重叠时也不会重复计算,即从2-3开始,即使两个不同的操作员都在一个小时内,也应该只有1小时的覆盖时间。任何帮助表示赞赏。
答案 0 :(得分:1)
对不起,工作打扰了我。
这是我的工作解决方案,由于联接的(相对)昂贵的性质,我不认为它是最佳的,但是我基于“转移”从未跨越多天的软规则对它进行了稍微的优化。 / p>
SELECT
calendar_date,
SUM(coverage_seconds) / 3600 AS coverage_hours
FROM
(
-- Signins that didn't happen within another operators shift
SELECT DISTINCT
DATE(e.signedin) AS calendar_date,
-(UNIX_TIMESTAMP(e.signedin) MOD 86400) AS coverage_seconds
FROM
OperatorLogs e
LEFT JOIN
OperatorLogs o
ON o.signedin >= DATE(e.signedin)
AND o.signedin < e.signedin
AND o.signedout >= e.signedin
WHERE
o.signedin IS NULL
UNION ALL
-- Signouts that didn't happen within another operators shift
SELECT DISTINCT
DATE(e.signedout) AS calendar_date,
+(UNIX_TIMESTAMP(e.signedout) MOD 86400) AS coverage_seconds
FROM
OperatorLogs e
LEFT JOIN
OperatorLogs o
ON o.signedin >= DATE(e.signedout)
AND o.signedin <= e.signedout
AND o.signedout > e.signedout
WHERE
o.signedin IS NULL
)
AS coverage_markers
GROUP BY
calendar_date
;
随时使用更严格的数据进行测试...
(请注意,为使示例数据与excel图像匹配,您的第一个班次应该在上午9点开始)