SQL SELECT查询返回重复记录:如何获取唯一ID及问题解决
重复原因分析
- 多表连接产生笛卡尔积:
members与system_data通过facility_id关联时,若同一facility_id对应多条system_data记录,单条members会被复制为多行。后续与logs连接时,同一个logs.id会绑定到这些重复的members行上,最终即使按logs.id分组,只要其他分组字段(如province/district)存在差异或因连接产生重复行,就会出现logs.id重复的结果。 - 左连接被转为内连接:
where子句中province is not null的条件,过滤掉了system_data无匹配的members记录,使得原本的左连接实际等同于内连接,进一步增加了连接后的重复行数。 - 分组逻辑冗余:原查询的分组字段包含
facility/time/province/district,这些字段与logs.id并非一一对应时,同一个logs.id会被分到多个分组中,导致结果重复;同时count(members.id)因连接产生的重复行,统计结果也不准确。
解决重复问题的方案
根据业务需求,提供两种可行思路:
思路1:先聚合去重,再关联日志表
先对members和system_data的关联结果做去重聚合,再与logs连接,避免笛卡尔积:
select logs.id, to_char(logs.login, 'YYYY-mm-dd') as time, m.facility, m.province, m.district, m.member_count as value from logs left join ( select members.card_id, members.facility_id as facility, max(system_data.province) as province, max(system_data.district) as district, count(distinct members.id) as member_count from members join system_data on system_data.facility_id = members.facility_id where system_data.province is not null group by members.card_id, members.facility_id ) m on logs.card_id = m.card_id and logs.facility_id = m.facility_id where '2022-08-01' <= logs.login and logs.login <= '2022-08-11' order by logs.id;
说明:子查询按card_id+facility_id分组,确保每个组合仅返回一条记录;用max()提取同一分组下的province/district(需确保同一facility_id下这些字段值一致),count(distinct)统计真实的成员数量。
思路2:调整分组逻辑,仅按logs.id分组
保留原查询结构,通过聚合函数确保同一logs.id仅返回一条记录:
select logs.id, to_char(max(logs.login), 'YYYY-mm-dd') as time, max(members.facility_id) as facility, max(system_data.province) as province, max(system_data.district) as district, count(distinct members.id) as value from members join system_data on system_data.facility_id = members.facility_id join logs on logs.card_id = members.card_id and members.facility_id = logs.facility_id where '2022-08-01' <= logs.login and logs.login <= '2022-08-11' and system_data.province is not null group by logs.id order by logs.id;
说明:将左连接改为内连接(原where条件已过滤无匹配的记录),仅按logs.id分组;对其他字段用max()取唯一值,count(distinct)避免重复统计成员数。
额外注意
- 明确
login字段来源:原查询未指定表名,若members和logs均有该字段会产生歧义,建议改为logs.login或members.login。 - 若同一
facility_id对应不同province/district,需先确认业务逻辑,再调整聚合方式(如筛选特定记录)。
内容的提问来源于stack exchange,提问作者FaFa
相关产品推荐
相关产品推荐

