SELECT pp.company_id AS companyId, pc.company_name AS companyName, COUNT(pp.id_card_no) AS count FROM project_personnel pp LEFT JOIN project_company pc ON pp.company_id = pc.id WHERE pp.project_id ='qj60f5928cc780fb42543cb3a5' AND pp.cur_state = 'IN' AND pp.create_time < '2025-02-27 23:59:59' GROUP BY pp.company_id SELECT companyId, SUM(times) times FROM( SELECT pp.company_id AS companyId, COUNT(DISTINCT DATE(tpar.create_time)) AS times FROM project_personnel pp LEFT JOIN tj_personnel_attendance_record tpar ON pp.id_card_no = tpar.id_card_no AND pp.post_name = tpar.post_name AND pp.company_id = tpar.company_id WHERE tpar.project_id ='qj60f5928cc780fb42543cb3a5' AND pp.cur_state = 'IN' AND tpar.create_time BETWEEN '2025-02-27 00:00:00' AND '2025-02-27 23:59:59' GROUP BY pp.company_id,tpar.id_card_no) a GROUP BY companyId把这俩查询结果放一起最后要pp.company_id AS companyId, pc.company_name AS companyName, COUNT(pp.id_card_no) AS count SUM(times) times 分别是公司ID,公司名称,在册人数,到岗人数
第一个查询是从project_personnel表左连接project_company表,按company_id分组,统计每个公司的在册人数。条件是项目ID、当前状态为IN,并且创建时间在2025年2月27日之前。这里要注意的是,LEFT JOIN可能会包含那些在project_company中没有对应记录的公司,但company_id来自pp,所以可能没问题。
第二个查询稍微复杂一点,子查询里先按公司和身份证号分组,统计每个员工在指定日期的考勤记录次数,即每天到岗一次。外层再按公司汇总,得到每个公司的总到岗人次。这里用了COUNT(DISTINCT DATE(create_time)),应该是计算每个员工在当天有多少次不同的日期记录,也就是每天算一次到岗。然后外层SUM这些次数,得到每个公司的总到岗人数。
现在的问题是如何把这两个查询的结果合并到一起。因为都是按company_id分组,所以可能需要使用JOIN将两个结果集连接起来。考虑到可能有公司没有到岗记录,所以应该用LEFT JOIN,这样即使第二个查询中没有对应的companyId,也能显示在册人数,而到岗人数为0或NULL。
接下来,我需要分别处理两个查询作为子查询,比如第一个查询的结果作为a,第二个作为b,然后通过companyId进行左连接。这样就能将两个统计结果合并到一个表中。需要注意的是,如果第二个查询中没有对应的companyId,SUM(times)可能会是NULL,所以需要使用COALESCE或者IFNULL函数将其转换为0,确保显示正确。
另外,检查字段是否正确,比如第一个查询的count是COUNT(pp.id_card_no),而第二个的times是SUM子查询中的times。确保连接条件正确,并且字段名对应。最后,可能需要将结果中的NULL转换为0,使数据更直观。
还需要确认两个查询中的project_id是否一致,第一个是pp.project_id,第二个是tpar.project_id,但用户给的查询中第二个的条件是tpar.project_id,这可能会有问题,如果tpar中没有对应project_id的记录,可能会影响结果。不过根据查询逻辑,可能没问题,因为已经通过LEFT JOIN连接了tj_personnel_attendance_record,但WHERE条件中的tpar.project_id可能会过滤掉没有考勤记录的情况。不过用户的需求可能就是要统计有考勤记录的到岗人数,所以可能正确。
最后,组合两个查询,使用LEFT JOIN,并处理NULL值,得到最终的四个字段:companyId, companyName, count, times。这里提供两种方法将两个查询结果合并:
使用JOIN合并查询(推荐):
SELECT a.companyId, a.companyName, a.count AS 在册人数, COALESCE(b.times, 0) AS 到岗人数 FROM ( SELECT pp.company_id AS companyId, pc.company_name AS companyName, COUNT(pp.id_card_no) AS count FROM project_personnel pp LEFT JOIN project_company pc ON pp.company_id = pc.id WHERE pp.project_id ='qj60f5928cc780fb42543cb3a5' AND pp.cur_state = 'IN' AND pp.create_time < '2025-02-27 23:59:59' GROUP BY pp.company_id, pc.company_name ) a LEFT JOIN ( SELECT companyId, SUM(times) times FROM( SELECT pp.company_id AS companyId, COUNT(DISTINCT DATE(tpar.create_time)) AS times FROM project_personnel pp LEFT JOIN tj_personnel_attendance_record tpar ON pp.id_card_no = tpar.id_card_no AND pp.post_name = tpar.post_name AND pp.company_id = tpar.company_id WHERE tpar.project_id ='qj60f5928cc780fb42543cb3a5' AND pp.cur_state = 'IN' AND tpar.create_time BETWEEN '2025-02-27 00:00:00' AND '2025-02-27 23:59:59' GROUP BY pp.company_id, tpar.id_card_no ) sub GROUP BY companyId ) b ON a.companyId = b.companyId;
使用UNION合并查询: ```sql SELECT companyId, companyName, count AS 在册人数, times AS 到岗人数 FROM ( -- 第一个查询 SELECT pp.company_id AS companyId, pc.company_name AS companyName, COUNT(pp.id_card_no) AS count, NULL AS times
FROM project_personnel pp LEFT JOIN project_company pc ON pp.company_id = pc.id WHERE pp.project_id ='qj60f5928cc780fb42543cb3a5' AND pp.cur_state = 'IN' AND pp.create_time < '2025-02-27 23:59:59' GROUP BY pp.company_id, pc.company_nameUNION ALL
-- 第二个查询 SELECT companyId, NULL AS companyName, NULL AS count, SUM(times) times FROM(
SELECT pp.company_id AS companyId, COUNT(DISTINCT DATE(tpar.create_time)) AS times
FROM project_personnel pp LEFT JOIN tj_personnel_attendance_record tpar ON pp.id_card_no = tpar.id_card_no AND pp.post_name = tpar.post_name AND pp.company_id = tpar.company_id WHERE tpar.project_id ='qj60f5928cc780fb42543cb3a5' AND pp.cur_state = 'IN' AND tpar.create_time BETWEEN '2025-02-27 00:00:00' AND '2025-02-27 23:59:59' GROUP BY pp.company_id, tpar.id_card_no ) sub GROUP BY companyId
) combined GROUP BY companyId, companyName;
```
主要差异说明:
- JOIN方法(推荐):
- 使用LEFT JOIN确保所有公司信息完整
- COALESCE处理空值
- 执行效率更高
- 结果更直观
- UNION方法:
- 合并两个结果集
- 需要处理NULL值
- 适合需要纵向合并的场景
最终字段说明:
companyId
:公司IDcompanyName
:公司名称在册人数
:符合条件的人员总数到岗人数
:指定日期内的实际到岗人次
注意:建议使用JOIN方法,它更符合业务逻辑且效率更高。如果某些公司没有考勤记录,到岗人数会显示为0。
相关推荐












