多项目客户取最低Rank,单项目客户保留数据的SQL查询需求
解决方案
问题分析
你遇到的核心问题是:用常规分组/窗口函数筛选最低Rank时,单项目且Rank为Null的记录会因Null无法参与等值比较(SQL中Null = 任何值都返回Unknown,会被WHERE条件过滤)而丢失。
方法一:窗口函数+条件筛选
通过窗口函数先统计每个客户的项目数,同时计算其最低Rank,再根据项目数分支处理:
WITH ClientProjectMetrics AS ( SELECT ClientKey, ProjectKey, Rank, -- 统计当前客户的项目总数 COUNT(ProjectKey) OVER (PARTITION BY ClientKey) AS TotalProjects, -- 计算当前客户的最低Rank(自动忽略Null,若全为Null则返回Null) MIN(Rank) OVER (PARTITION BY ClientKey) AS MinRank FROM YourTableName ) SELECT ClientKey, ProjectKey, Rank FROM ClientProjectMetrics WHERE -- 单项目客户:直接保留所有记录(包括Rank为Null的) TotalProjects = 1 -- 多项目客户:仅保留Rank等于最低Rank的记录,同时兼容全Null的情况 OR (TotalProjects > 1 AND (Rank = MinRank OR (MinRank IS NULL AND Rank IS NULL)))
方法二:LEFT JOIN聚合结果
如果你不习惯用CTE,也可以通过左关联客户的聚合统计结果来实现,避免INNER JOIN导致的记录丢失:
SELECT t.ClientKey, t.ProjectKey, t.Rank FROM YourTableName t LEFT JOIN ( SELECT ClientKey, COUNT(ProjectKey) AS TotalProjects, MIN(Rank) AS MinRank FROM YourTableName GROUP BY ClientKey ) c_stats ON t.ClientKey = c_stats.ClientKey WHERE c_stats.TotalProjects = 1 OR (c_stats.TotalProjects > 1 AND (t.Rank = c_stats.MinRank OR (c_stats.MinRank IS NULL AND t.Rank IS NULL)))
关键注意点
- 必须用
LEFT JOIN而非INNER JOIN,否则单项目且Rank为Null的客户会因为聚合子查询中MIN(Rank)为Null而被过滤。 - 处理多项目且全Rank为Null的场景:必须单独判断
MinRank IS NULL AND Rank IS NULL,因为SQL中Null = Null不成立,无法通过等值比较匹配。
内容的提问来源于stack exchange,提问作者hubert
相关产品推荐
相关产品推荐

