SQL中如何选取多列并按其中2-3列执行分组查询?
现有语句的问题
- 分组粒度和业务目标不匹配:你的业务逻辑是按客户唯一标识SSN统计活跃联系人数量,当前
GROUP BY SSN,ClientTypeId会拆分同SSN下不同ClientTypeId的记录,而WHERE条件已经固定筛选活跃客户对应的ClientTypeId,该字段加入分组属于冗余操作。 - SELECT列表包含未聚合、也未加入分组规则的
Id字段,在标准SQL模式下会直接抛出语法错误——同一个SSN分组对应多个联系人Id,数据库无法确定要返回哪条记录的Id值。 - 缺少分组后过滤逻辑:没有加
HAVING子句筛选联系人数量大于1的分组,会返回所有活跃客户,不管对应多少个联系人。
实现方案
根据你需要返回的字段类型,分两种场景写:
场景1:返回客户维度汇总结果
如果你要返回的5-6列都是客户级别的固定属性(同一个SSN下这些字段值完全一致,比如客户姓名、注册时间、所属客户经理等),直接把所有非聚合字段加入分组规则,再加HAVING过滤即可:
SELECT SSN, ClientTypeId, -- 按需补充其他客户属性字段,比如CustomerName、RegisterTime、OwnerId等 COUNT(SSN) AS ActiveContactCount FROM Contact WHERE ClientTypeId = '活跃客户对应的GUID值' GROUP BY SSN, ClientTypeId -- 上面SELECT里写了几个非聚合字段,这里就对应列几个 HAVING COUNT(SSN) > 1 -- 核心过滤:只保留存在2个及以上活跃联系人的客户
只要SELECT里的非聚合字段和SSN是一一对应关系,不管加多少个字段到GROUP BY,都不会改变按客户统计的粒度,结果不会出错。
场景2:返回联系人维度明细结果
如果你要返回的字段包含联系人级别的属性(同一个SSN下这些字段值不同,比如联系人Id、联系电话、联系人添加时间等),先通过子查询筛出符合多联系人条件的SSN,再关联原表取全量字段即可,所有支持SQL92标准的数据库都能运行:
SELECT c.SSN, c.ClientTypeId, c.Id AS ContactId, -- 按需补充其他需要的字段,比如c.ContactPhone、c.CreateTime、c.ContactName等 FROM Contact c INNER JOIN ( SELECT SSN FROM Contact WHERE ClientTypeId = '活跃客户对应的GUID值' GROUP BY SSN HAVING COUNT(1) > 1 ) mcc ON c.SSN = mcc.SSN WHERE c.ClientTypeId = '活跃客户对应的GUID值'
内容的提问来源于stack exchange,提问作者znat0k
相关产品推荐
相关产品推荐

