You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python工时统计循环异常:重复显示员工总工时条目求助

解决工时表管理系统中员工总工时重复计算的问题

看起来你在计算员工总工时的时候踩了几个常见的逻辑坑,咱们一步步理清楚问题,然后给出更简洁可靠的实现方案。

现有代码的核心问题

从你的输出和代码来看,导致Chris总工时重复的原因主要有这几点:

  • 重复遍历触发多次计算:你的secondNameList包含重复的"Chris"条目,循环每遇到一次就会重新计算一次他的总工时,自然会生成多条重复记录。
  • 变量引用与计算逻辑混乱:代码里tdelta是外部变量,没有和当前遍历的员工条目绑定,而且totalMinutes和totalMinutesPerPerson混用(比如totalHoursPerPerson += totalMinutes // 60里的totalMinutes未定义),导致计算结果出错。
  • 用set去重治标不治本:set只能去除完全相同的字符串,但你的问题根源是循环逻辑错误,去重后反而会留下矛盾的计算结果(比如Chris既有9小时又有18小时的记录)。

优化方案

方案一:让数据库直接完成统计(推荐)

利用MySQL的分组和日期计算功能,直接从数据库获取每个员工的总工时,既高效又能避免前端逻辑错误,还能解决SQL注入风险:

修改SQL查询语句

SELECT 
    FirstName, 
    LastName,
    -- 计算每条记录的工时秒数,求和后转成时间格式
    SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND, StartTime, FinishTime))) AS TotalHours
FROM Sheets 
WHERE DateTesting >= %s AND DateTesting <= %s
GROUP BY FirstName, LastName;

Python端执行代码(参数化查询,避免SQL注入)

import datetime
import mysql.connector

# 假设已建立数据库连接
conn = mysql.connector.connect(host='your_host', user='your_user', password='your_pass', database='your_db')
cursor = conn.cursor()

# 使用参数化查询,绝对不要用字符串拼接传递参数!
query = """
SELECT 
    FirstName, 
    LastName,
    SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND, StartTime, FinishTime))) AS TotalHours
FROM Sheets 
WHERE DateTesting >= %s AND DateTesting <= %s
GROUP BY FirstName, LastName;
"""

# 传递日期参数
cursor.execute(query, (StartDate, EndDate))
results = cursor.fetchall()

# 展示结果到UI
for first_name, last_name, total_hours in results:
    print(f'{first_name} {last_name} did a total of {total_hours} Hours')
    self.labels.append(Label(myframe, text=f'Name: {first_name} {last_name} | Total Hours: {total_hours}'))
    self.labels[-1].grid(column=0, row=len(self.labels)-1)

cursor.close()
conn.close()

这个方案的优势:

  • 数据库处理分组统计效率更高,减少Python端的计算负担
  • 从根源避免循环逻辑错误
  • 参数化查询彻底解决原代码的SQL注入风险

方案二:Python端分组计算总工时

如果必须在Python端处理数据,推荐用字典按员工全名分组累计工时,逻辑清晰且不易出错:

import datetime

# 假设从数据库获取的原始记录列表
time_records = [('Chris', 'Gracey', '07:00', '16:30'), 
                ('Chris', 'Gracey', '07:00', '16:30'), 
                ('Rory', 'Gracey', '07:00', '16:30'), 
                ('John', 'Smith', '07:00', '16:30')]
FMT = '%H:%M'

# 用字典存储每个员工的总分钟数,键为员工全名
employee_totals = {}

for first_name, last_name, start_time, finish_time in time_records:
    # 计算单条记录的工时分钟数
    start_dt = datetime.datetime.strptime(start_time, FMT)
    finish_dt = datetime.datetime.strptime(finish_time, FMT)
    delta = finish_dt - start_dt
    record_minutes = delta.total_seconds() // 60
    
    # 累计到对应员工的总工时
    full_name = f'{first_name} {last_name}'
    if full_name in employee_totals:
        employee_totals[full_name] += record_minutes
    else:
        employee_totals[full_name] = record_minutes

# 转换为易读的格式并生成结果列表
totals_per_person = []
for name, total_min in employee_totals.items():
    hours = total_min // 60
    minutes = total_min % 60
    totals_per_person.append(f'{name} did a total of {hours} Hours {minutes} Minutes')

# 输出并展示
for line in totals_per_person:
    print(line)
    # UI展示逻辑
    self.labels.append(Label(myframe, text=line))
    self.labels[-1].grid(column=0, row=len(self.labels)-1)

这个方案的优势:

  • 逻辑清晰,避免重复遍历和变量混用
  • 直接按员工分组累计,不会生成重复记录
  • 计算过程透明,便于调试和维护

内容的提问来源于stack exchange,提问作者Rory Gracey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:47:06