SQL新手求助:如何过滤matches表中的冗余板球赛事记录?
问题描述
matches表存储不同球队间的板球赛事数据及获胜队伍信息,表结构和数据如下:
| Team_1 | Team_2 | Winner |
|---|---|---|
| CSK | MI | MI |
| MI | CSK | MI |
| MI | KKR | MI |
| RCB | RR | RR |
| RCB | RR | RR |
| KKR | MI | MI |
需要编写SQL查询过滤表中的冗余记录:比如第1行和第2行属于同一对阵组合(仅球队顺序颠倒),结果表中仅需保留其中一行;同时RCB与RR的重复对阵也只留一行。
尝试用自连接解决但因球队顺序不固定(部分对阵顺序固定、部分颠倒)未能成功,求可行方案。
解决方案:统一对阵组合标识去重
核心思路是把任意顺序的两个球队,转换成固定顺序的组合标识,以此识别出重复的对阵,再进行去重操作。以下是两种适合新手的实现方法:
方法1:快速去重(保留任意一行)
利用LEAST和GREATEST函数,将每组对阵的球队按字母顺序固定排列,再通过DISTINCT去掉重复组合:
SELECT DISTINCT LEAST(Team_1, Team_2) AS Team_A, GREATEST(Team_1, Team_2) AS Team_B, Winner FROM matches;
LEAST(a,b)返回两个值中"更小"的(字符串按字母顺序比较),GREATEST(a,b)返回"更大"的,这样不管原数据中球队顺序如何,同一对阵都会生成相同的Team_A和Team_B。- 执行后,CSK与MI的对阵会统一显示为
CSK和MI,重复的组合会被自动过滤。
方法2:保留指定行(如最早/最新记录)
如果需要保留每组对阵的特定行(比如最早的赛事记录),可以用窗口函数ROW_NUMBER()先给每组对阵分配行号,再筛选行号为1的记录:
WITH ranked_matches AS ( SELECT Team_1, Team_2, Winner, ROW_NUMBER() OVER ( PARTITION BY LEAST(Team_1, Team_2), GREATEST(Team_1, Team_2) ORDER BY match_id ASC -- 若有赛事ID/日期字段,用它排序保留指定记录 ) AS rn FROM matches ) SELECT Team_1, Team_2, Winner FROM ranked_matches WHERE rn = 1;
- 如果表中没有排序字段,把
ORDER BY match_id ASC改成ORDER BY (SELECT NULL)即可保留任意一行。
兼容小众数据库的替代写法
如果你的数据库不支持LEAST/GREATEST,可以用CASE语句实现相同逻辑:
SELECT DISTINCT CASE WHEN Team_1 < Team_2 THEN Team_1 ELSE Team_2 END AS Team_A, CASE WHEN Team_1 < Team_2 THEN Team_2 ELSE Team_1 END AS Team_B, Winner FROM matches;
内容的提问来源于stack exchange,提问作者Rashq1
相关产品推荐
相关产品推荐

