SQL查询需求:同类型下保留最长strWord的非重复描述行
解决同类型下重复描述保留最长单词行的SQL方案
我来帮你搞定这个需求!咱们要处理的是一张包含strWord、strWordType、strWordDescription三列的表,核心要求很明确:
- 当
strWordType相同时,如果有重复的strWordDescription,只留下strWord长度最长的那一行 - 没有重复描述的行全部保留
- 还不能用
DISTINCT关键字,而且已知strWord和strWordType的组合是唯一的,只有特定类型下会出现重复描述
先看你给出的示例表:
-- 示例表 myTable strWord | strWordType | strWordDescription blue | 2012 | This is a color blue | 2014 | This is a color green | 2012 | This is a color ham | 2014 | This is a food chicken | 2014 | This is a food
预期要得到的结果是:
-- 预期结果 strWord | strWordType | strWordDescription green | 2012 | This is a color blue | 2014 | This is a color chicken | 2014 | This is a food
解决方案:用窗口函数实现分组排序筛选
最适合这个场景的就是窗口函数ROW_NUMBER(),它能帮我们在分组内排序,轻松选出每个分组里的目标行,而且完全不用DISTINCT。具体SQL代码如下:
WITH ranked_words AS ( SELECT strWord, strWordType, strWordDescription, -- 按类型+描述分组,组内按单词长度倒序排,最长的行rn=1 ROW_NUMBER() OVER ( PARTITION BY strWordType, strWordDescription ORDER BY LENGTH(strWord) DESC ) AS rn FROM myTable ) -- 只保留每个分组里排名第一的行 SELECT strWord, strWordType, strWordDescription FROM ranked_words WHERE rn = 1;
代码逻辑解释
- 分组规则:
PARTITION BY strWordType, strWordDescription把数据拆分成「同一类型+同一描述」的小组,这样同一类型下重复描述的行会被归到同一个小组里。 - 排序规则:
ORDER BY LENGTH(strWord) DESC在每个小组内,按strWord的长度从长到短排序,长度最长的行就会被标记为rn=1。 - 筛选结果:最后只取
rn=1的行,既保留了无重复描述的行(这类小组只有一行,自然rn=1),也保留了重复描述小组里最长单词的行。
小提示
不同数据库的字符串长度函数可能略有差异:
- MySQL/Oracle:用
LENGTH()(注意MySQL中LENGTH是字节长度,若要字符长度用CHAR_LENGTH()) - SQL Server:用
LEN()
根据你使用的数据库调整即可,核心逻辑是一致的。
内容的提问来源于stack exchange,提问作者CompSciFly




