Redshift SQL:按规则去重并筛选表数据的实现方案
解决ID按Code去重并保留指定行的SQL方案
方案一:使用窗口函数(推荐,兼容多数现代数据库)
通过窗口函数先标记每个ID的状态,再筛选符合条件的行:
WITH id_status AS ( SELECT *, -- 标记当前ID是否存在Code='Y'的记录 MAX(CASE WHEN Code = 'Y' THEN 1 ELSE 0 END) OVER (PARTITION BY ID) AS has_y, -- 按Amount降序排名,用于无Y时取最大值行 RANK() OVER (PARTITION BY ID ORDER BY Amount DESC) AS amount_rank FROM your_table ) SELECT ID, Code, Amount -- 替换为你实际需要的列 FROM id_status WHERE (has_y = 1 AND Code = 'Y') OR (has_y = 0 AND amount_rank = 1);
说明:
has_y字段会给同一个ID下的所有行标记为1(只要该ID存在Code='Y'的记录),否则为0。amount_rank给每个ID下的行按Amount从大到小排名,最大值的行排名为1。- 如果需要确保无Y时只返回唯一一行(即使多个行Amount相同),把
RANK()换成ROW_NUMBER(),可以额外加排序字段保证稳定性,比如ORDER BY Amount DESC, CreateTime DESC(假设存在CreateTime列)。
方案二:使用UNION ALL + 子查询(适合不支持窗口函数的旧版数据库)
分两部分查询后合并结果:
-- 第一部分:保留所有含Code='Y'的行 SELECT ID, Code, Amount FROM your_table WHERE Code = 'Y' UNION ALL -- 第二部分:保留无Code='Y'的ID中Amount最大的行 SELECT t.ID, t.Code, t.Amount FROM your_table t WHERE -- 筛选出没有Code='Y'记录的ID NOT EXISTS (SELECT 1 FROM your_table y WHERE y.ID = t.ID AND y.Code = 'Y') -- 取当前ID下的最大Amount行 AND t.Amount = (SELECT MAX(Amount) FROM your_table WHERE ID = t.ID);
说明:
- 用
UNION ALL而非UNION,因为两部分的ID无重叠,避免不必要的去重开销。 - 用
NOT EXISTS替代NOT IN可以避免ID为NULL时的异常问题。
注意事项
- 替换
your_table和ID, Code, Amount为你实际的表名和列名。 - 如果表数据量极大,建议给
ID、Code字段建立索引,提升子查询或窗口函数的执行效率。
内容的提问来源于stack exchange,提问作者winlai
相关产品推荐
相关产品推荐

