全员战报明细到店数统计问题修复.md
5.02 KB
全员战报明细到店数统计问题修复
📋 问题描述
在全员战报明细统计中,发现有的数据的到店数比拓客数还多,不符合业务逻辑。
业务规则:
- 一个人多次到店的话在这里就算一次
- 到店数应该小于等于拓客数
🔍 问题分析
问题位置
文件: netcore/src/Modularity/Extend/NCC.Extend/LqTkDashboardService.cs
方法: GetEmployeeParticipationStatistics
行数: 第575-588行(修复前)
问题原因
修复前的SQL逻辑:
LEFT JOIN (
-- 到店人数统计
SELECT
tk.F_ExpansionUserId as EmployeeId,
COUNT(DISTINCT tk.F_MemberId) as VisitCount
FROM lq_tkjlb tk
INNER JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy AND xh.F_IsEffective = 1
WHERE {eventFilter}
AND tk.F_ExpansionTime >= '{startTimeStr}'
AND tk.F_ExpansionTime <= '{endTimeStr}'
AND xh.hksj >= '{startTimeStr}'
AND xh.hksj <= '{endTimeStr}'
GROUP BY tk.F_ExpansionUserId
) visit ON emp.EmployeeId = visit.EmployeeId
问题点:
- 缺少时间关联约束:没有限制到店时间必须在拓客时间之后,可能统计到拓客之前的到店记录
- JOIN导致重复计数:当同一个会员被同一个员工多次拓客,且该会员多次到店时,
INNER JOIN会产生多行记录 - 虽然使用了 DISTINCT,但 JOIN 的逻辑可能导致计数不准确
问题场景示例
假设:
- 员工A在1月1日拓客了会员B
- 员工A在1月5日又拓客了会员B(重复拓客)
- 会员B在1月3日到店1次
- 会员B在1月6日到店1次
修复前的统计结果:
- 拓客数:1(COUNT(DISTINCT tk.F_MemberId))
- 到店数:2(因为 JOIN 产生了2条记录:1月1日拓客+1月3日到店,1月5日拓客+1月6日到店)
问题:到店数(2)> 拓客数(1),不符合逻辑
✅ 修复方案
修复后的SQL逻辑(最终版本)
LEFT JOIN (
-- 到店人数统计(一个人多次到店只算一次)
-- 先找出每个员工拓客的所有会员(去重),然后统计这些会员中有到店记录的会员数
SELECT
emp_members.EmployeeId,
COUNT(DISTINCT CASE WHEN xh.hy IS NOT NULL THEN emp_members.MemberId END) as VisitCount
FROM (
-- 先获取每个员工拓客的所有会员(去重),并记录首次拓客时间
SELECT DISTINCT
tk.F_ExpansionUserId as EmployeeId,
tk.F_MemberId as MemberId,
MIN(tk.F_ExpansionTime) as FirstExpansionTime
FROM lq_tkjlb tk
WHERE {eventFilter}
AND tk.F_ExpansionTime >= '{startTimeStr}'
AND tk.F_ExpansionTime <= '{endTimeStr}'
AND tk.F_MemberId IS NOT NULL
GROUP BY tk.F_ExpansionUserId, tk.F_MemberId
) emp_members
LEFT JOIN lq_xh_hyhk xh ON emp_members.MemberId = xh.hy
AND xh.F_IsEffective = 1
AND xh.hksj >= emp_members.FirstExpansionTime
AND xh.hksj >= '{startTimeStr}'
AND xh.hksj <= '{endTimeStr}'
GROUP BY emp_members.EmployeeId
) visit ON emp.EmployeeId = visit.EmployeeId
修复要点
先获取拓客会员列表(去重):
- 使用子查询先找出每个员工拓客的所有会员(去重)
- 记录每个会员的首次拓客时间(
MIN(tk.F_ExpansionTime)) - 确保同一个会员只出现一次,即使被多次拓客
统计有到店记录的会员数:
- 在去重后的会员列表中,LEFT JOIN 耗卡表
- 使用
COUNT(DISTINCT CASE WHEN xh.hy IS NOT NULL THEN emp_members.MemberId END)统计有到店记录的会员数 - 确保到店时间在首次拓客时间之后(
xh.hksj >= emp_members.FirstExpansionTime)
双重去重保障:
- 第一层:在子查询中使用
GROUP BY tk.F_ExpansionUserId, tk.F_MemberId确保每个员工-会员组合只出现一次 - 第二层:使用
COUNT(DISTINCT ...)确保最终统计时每个会员只算一次
- 第一层:在子查询中使用
修复后的统计结果(使用上面的示例)
- 拓客数:1(COUNT(DISTINCT tk.F_MemberId))
- 到店数:1(会员B有到店记录,只算一次)
结果:到店数(1)≤ 拓客数(1),符合逻辑 ✅
📝 修改文件
- 文件:
netcore/src/Modularity/Extend/NCC.Extend/LqTkDashboardService.cs - 方法:
GetEmployeeParticipationStatistics - 修改位置: 第575-590行
✅ 验证建议
- 验证到店数 ≤ 拓客数:检查所有员工的统计数据,确保到店数不超过拓客数
- 验证去重逻辑:选择一个多次到店的会员,验证其只被统计一次
- 验证时间约束:选择一个拓客前有到店记录的会员,验证不会被统计到
🔗 相关接口
接口地址: POST /api/Extend/LqTkDashboard/GetEmployeeParticipationStatistics
接口说明: 获取员工参与统计(全员战报明细)
返回字段:
ExpansionCount: 拓客数VisitCount: 到店数(修复后)BillingCount: 开单数BillingAmount: 开单金额