如何在SQL查询中按员工姓名拆分获取月度报表数据
问题描述
现有三张数据表:
Table_Project
ProjectId ProjectName ------------------------- 1 A 2 B 3 C
Table_Employee
EmployeeId Name -------------------------- 1 Jhon 2 Jason
Table_Task
Id ProjectId EmployeeId TaskName TaskMinute StartDate EndDate --------------------------------------------------------------------------------------- 1 1 1 xyz1 10 2024/03/17 2024/03/17 2 2 1 xyz2 30 2024/03/17 2024/03/17 3 1 1 xyz3 40 2024/03/17 2024/03/17 4 2 2 kkk 90 2024/03/17 2024/03/17 5 3 2 kk1 10 2024/03/17 2024/03/17
需求:查询EndDate属于当月的数据,按员工拆分展示,包含员工姓名、项目名、任务名、任务时长,每个员工数据末尾添加该员工的任务时长总计,期望输出格式如下:
Jhon ProjectName TaskName TaskMinute A xyz1 10 B xyz2 30 A xyz3 40 Total 80 Jason B kkk 90 C kk1 10 Total 100
本人尝试使用内连接编写SQL,但未梳理出正确逻辑,尝试的SQL语句如下:
select P.ProjectName,e.Name,t.TaskMinute from Table_Task t inner join Table_Project p on t.projectid=p.ProjectIdId inner join Table_Employee e on t.employeeid=e.EmployeeId group by ProjectName, e.Name t.TaskMinute
请问是否可以实现上述输出,或获取包含同等信息的其他展示方式?
解决方案
一、能否实现指定格式?
可以通过SQL实现近似的结构化输出,但完全匹配你给出的缩进、姓名仅首行显示的格式,更适合在前端应用或报表工具中处理。SQL本身擅长输出规整数据集,不过可以通过拼接明细行和合计行的方式,实现包含核心信息的结构化结果。
二、具体实现方案
方案1:SQL生成带合计行的数据集
以下SQL会输出每个员工的任务明细,以及对应的合计行,通过排序确保合计行在每个员工数据的最后:
-- 任务明细行 SELECT e.Name AS 员工姓名, p.ProjectName AS 项目名, t.TaskName AS 任务名, t.TaskMinute AS 任务时长, 1 AS sort_flag -- 标记为明细行,排序时靠前 FROM Table_Task t JOIN Table_Project p ON t.ProjectId = p.ProjectId JOIN Table_Employee e ON t.EmployeeId = e.EmployeeId WHERE DATE_FORMAT(t.EndDate, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') -- 筛选当月数据 UNION ALL -- 员工任务时长合计行 SELECT e.Name AS 员工姓名, '' AS 项目名, 'Total' AS 任务名, SUM(t.TaskMinute) AS 任务时长, 2 AS sort_flag -- 标记为合计行,排序时靠后 FROM Table_Task t JOIN Table_Employee e ON t.EmployeeId = e.EmployeeId WHERE DATE_FORMAT(t.EndDate, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') GROUP BY e.Name, e.EmployeeId -- 按员工姓名和标记排序,保证明细在前、合计在后 ORDER BY e.Name, sort_flag;
输出结果示例:
| 员工姓名 | 项目名 | 任务名 | 任务时长 |
|---|---|---|---|
| Jhon | A | xyz1 | 10 |
| Jhon | B | xyz2 | 30 |
| Jhon | A | xyz3 | 40 |
| Jhon | Total | 80 | |
| Jason | B | kkk | 90 |
| Jason | C | kk1 | 10 |
| Jason | Total | 100 |
方案2:前端/报表工具处理格式
如果想要完全实现你给出的缩进、姓名仅首行显示的格式,更推荐:
- 用SQL查询出规整的任务明细数据(不带合计),同时单独查询每个员工的总时长
- 在前端页面或报表工具(如Excel、Tableau)中,通过分组显示、隐藏重复姓名、添加合计行的功能来实现目标格式。这种方式更灵活,也符合数据处理的职责划分:SQL负责取数,前端/报表负责展示格式。
三、对你尝试的SQL的修正
你写的SQL存在几个问题:
- 关联条件错误:
t.projectid=p.ProjectIdId应为t.ProjectId = p.ProjectId(多写了一个Id) - GROUP BY语法错误:字段之间缺少逗号,且GROUP BY的字段与SELECT字段不匹配(如需分组统计,需配合聚合函数)
- 缺少筛选当月数据的条件
如果仅查询当月任务明细,正确的基础SQL应为:
SELECT e.Name AS 员工姓名, p.ProjectName AS 项目名, t.TaskName AS 任务名, t.TaskMinute AS 任务时长 FROM Table_Task t JOIN Table_Project p ON t.ProjectId = p.ProjectId JOIN Table_Employee e ON t.EmployeeId = e.EmployeeId WHERE DATE_FORMAT(t.EndDate, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') ORDER BY e.Name;
内容的提问来源于stack exchange,提问作者mr coder
相关产品推荐
相关产品推荐

