SQL子查询统计唯一行:按邮箱去重统计活动各尺码T恤数量
活动预订系统T恤尺码去重统计方案
业务场景说明
- 用户加购2场活动时仅需提交1次注册表单,填写姓名、邮箱、儿童数量、对应儿童T恤尺码,同一份尺码数据会在两场活动下重复存储
- 统计需求:计算第一场活动各T恤尺码的总需求数,排除第二场活动的重复记录
- 重复判定规则:以
jos_eb_registrants表的email字段作为唯一判重依据,同邮箱的多条注册记录仅保留1条有效统计记录 - 涉及表结构:
jos_eb_field_values:存储T恤尺码字段值,通过registrant_id关联注册主表jos_eb_registrants:存储注册记录核心信息,包含id(注册ID)、event_id(活动ID)、email(注册人邮箱)
- 示例校验逻辑:需统计
registrant_id=22434的尺码记录,忽略同邮箱绑定的registrant_id=22435重复记录
原有SQL错误点
原有去重子查询存在两类核心逻辑错误,无法实现去重效果:
- 子查询返回列数不匹配:同时返回注册ID、count聚合结果,和外层查询的关联条件不兼容
- 分组维度错误:按注册ID
id分组而非按去重依据email分组,完全无法识别同邮箱的重复记录
修正后SQL实现
核心逻辑:先按邮箱分组取每个邮箱对应的最小注册ID(即最早提交的第一场活动的注册记录,对应示例里的22434),再关联尺码表统计对应记录的尺码分布。
SELECT fv.field_value AS t_shirt_size, COUNT(fv.id) AS total_count FROM jos_eb_field_values fv INNER JOIN jos_eb_registrants r ON fv.registrant_id = r.id -- 过滤目标第一场活动,替换为实际的第一场活动ID WHERE r.event_id = 1 AND fv.field_name = 't_shirt_size' -- 替换为系统里T恤尺码对应的实际字段名 -- 去重逻辑:仅保留每个邮箱对应的最小注册ID记录,自动过滤同邮箱后续活动的重复注册记录 AND r.id IN ( SELECT MIN(id) FROM jos_eb_registrants -- 仅统计两场活动范围内的记录,避免引入无关活动数据 WHERE event_id IN (1,2) GROUP BY email ) GROUP BY fv.field_value ORDER BY total_count DESC;
PHP业务代码适配说明
嵌入原有PHP逻辑时,只需要替换原有错误的去重子查询部分即可:
- 不需要修改外层的尺码统计、结果遍历逻辑
- 活动ID、尺码字段名可通过系统现有配置变量动态传入,无需硬编码
- 如果需要支持多场活动的去重扩展,只需要调整子查询里的
event_id IN范围、外层的目标活动ID即可
校验提示:执行SQL后可单独查询
内容的提问来源于stack exchange,提问作者OnTarget
相关产品推荐
相关产品推荐

