如何在B、C列唯一时不选取A列重复的行
解决你的SQL查询需求
先明确下我理解的需求:你想要筛选出表中的行,规则是:
- 如果某行的
session和updated组合不唯一(即存在其他行和它的session、updated完全相同),无论对应的id是否重复,都保留该行; - 如果某行的
session和updated组合唯一,那么只有当对应的id在表中只出现一次时,才保留该行(反之,若id有重复,则排除该行)。
针对这个需求,我给你两种可行的SQL方案,分别适用于不同版本的数据库:
方案一:使用窗口函数(推荐,支持现代SQL数据库)
这种方法效率高,代码简洁,适用于MySQL 8.0+、PostgreSQL、SQL Server、Oracle等支持窗口函数的数据库。
WITH row_metrics AS ( SELECT id, session, updated, -- 计算当前(session, updated)组合的总行数 COUNT(*) OVER (PARTITION BY session, updated) AS su_occurrences, -- 计算当前id在表中的总行数 COUNT(*) OVER (PARTITION BY id) AS id_occurrences FROM your_table ) SELECT id, session, updated FROM row_metrics WHERE -- 保留session+updated组合不唯一的行 su_occurrences > 1 -- 或者组合唯一,但id只出现一次的行 OR (su_occurrences = 1 AND id_occurrences = 1);
逻辑解释:
- 首先用CTE(公共表表达式)
row_metrics给每一行添加两个统计值:su_occurrences:统计当前行的session+updated组合在表中出现的次数;id_occurrences:统计当前行的id在表中出现的总次数。
- 然后在主查询中,根据你的需求筛选行:要么组合有重复,要么组合唯一且id无重复。
方案二:使用子查询(兼容旧版数据库)
如果你的数据库不支持窗口函数(比如MySQL 5.x),可以用子查询关联的方式实现:
SELECT t.id, t.session, t.updated FROM your_table t -- 关联查询session+updated组合的出现次数 JOIN ( SELECT session, updated, COUNT(*) AS su_count FROM your_table GROUP BY session, updated ) su_stats ON t.session = su_stats.session AND t.updated = su_stats.updated -- 关联查询id的出现次数 JOIN ( SELECT id, COUNT(*) AS id_count FROM your_table GROUP BY id ) id_stats ON t.id = id_stats.id WHERE su_count > 1 OR (su_count = 1 AND id_count = 1);
针对你给出的示例数据验证
用你的示例数据测试的话,最终只会保留d | s2s2s2s2 | 2018-01-01这一行,其他行因为session+updated组合唯一但id重复,都会被排除,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Jeremy John
相关产品推荐
相关产品推荐

