Oracle Distinct查询需求:按年份统计唯一客户并保留其他列数据
解决方案:按年份去重客户并保留所有列(无GROUP BY)
你的问题核心是没有把年份(Year)纳入去重维度——原来的SELECT DISTINCT(CustomerID)只会对客户ID去重,完全忽略了年份,导致同一个客户跨不同年份只会显示一次,这显然不符合需求。下面给你两种不需要GROUP BY的实现方案,按需选择:
方案1:保留每年每个客户的单条记录(优先推荐)
如果希望同一年同一个客户只显示一条记录(不管其他业务字段的差异,比如取该客户当年的第一条访问记录),用ROW_NUMBER()窗口函数是最稳妥的方式:
SELECT * FROM ( SELECT *, -- 按年份+客户ID分区,给每个分区的行编号 ROW_NUMBER() OVER (PARTITION BY Year, CustomerID ORDER BY CustomerVisitID) AS row_num FROM CustomerVisits WHERE Year IN (2016,2017,2018,2019) ) AS visit_subquery -- 只取每个分区的第一条记录 WHERE row_num = 1;
说明:
PARTITION BY Year, CustomerID:把数据按「年份+客户ID」分成不同的组,每个组对应一个客户的某一年访问记录ORDER BY CustomerVisitID:决定每个组里哪条记录排在最前面(这里用访问ID,你也可以换成业务需要的字段,比如按访问时间排序取最新/最早的记录)- 外层筛选
row_num = 1,就能保证每年每个客户只保留一条记录,同时完整保留所有业务列数据
方案2:保留每年每个客户的所有唯一业务组合
如果业务上需要保留同一年同一个客户的所有不同业务字段组合(比如同一个客户同一年有不同的业务操作,需要全部展示,但重复的组合要去重),可以用多列DISTINCT:
-- 注意:必须明确列出需要保留的列,不能用SELECT * SELECT DISTINCT CustomerID, Year, BusinessField1, BusinessField2, -- 其他需要保留的业务字段 FROM CustomerVisits WHERE Year IN (2016,2017,2018,2019);
说明:
- 这里的
DISTINCT会基于所有列出的列去重,只有当所有列的值都完全相同时才会合并行 - 不能用
SELECT *,因为CustomerVisitID是唯一的,会导致所有行都被保留,失去去重效果
为什么原来的查询失效?
DISTINCT(CustomerID)本质上和DISTINCT CustomerID是一样的,只会根据客户ID这一列去重,完全不考虑年份维度。所以像CustomerID "5544"这样在2016和2018都有访问的客户,会被合并成一条记录,而不是按年份各显示一次。
内容的提问来源于stack exchange,提问作者Swaminathan K
相关产品推荐
相关产品推荐

