Oracle正则表达式SQL查询错误求助:Hackerrank Station问题排查
分析你这道Hackerrank题的SQL错误
先明确题目的核心要求:从station表中查询所有**开头字母和结尾字母都不是元音(a/e/i/o/u,不区分大小写)**的不重复城市名。
先看你写的SQL代码:
select distinct city from station where regexp_like(city,'^[^aeiou].*[^aeiou]$','i') and regexp_like(city,'^[^aeiou]\w+[^aeiou]$','i');
这里存在两个关键错误:
1. 冗余且限制过度的双重正则判断
你用and连接了两个regexp_like条件,完全是画蛇添足:
- 第一个正则
^[^aeiou].*[^aeiou]$已经在判断「开头非元音、结尾非元音,中间可以是任意字符」 - 第二个正则里的
\w+要求中间至少有一个字母/数字/下划线,这直接强制城市名长度至少为3(开头1位+中间至少1位+结尾1位),会漏掉长度为1或2的合法城市(比如单个字符的'Z'、两个字符的'XY'这类符合要求的案例)。
两个条件叠加后,既做了重复判断,还错误缩小了结果范围,不符合题目要求。
2. 第一个正则本身的逻辑漏洞
就算去掉第二个条件,第一个正则^[^aeiou].*[^aeiou]$也有问题:它无法匹配长度为1的合法城市。比如城市名是'B',它的开头和结尾都是非元音,但你的正则要求字符串同时满足「开头非元音」和「结尾非元音」,对于长度为1的字符串来说,这个正则相当于要求它有两个字符位,自然匹配失败,漏掉了这类有效数据。
正确写法推荐
你可以拆分判断逻辑,分别检查开头和结尾是否为非元音,这样更清晰且覆盖所有情况:
select distinct city from station where regexp_like(city, '^[^aeiou]', 'i') and regexp_like(city, '[^aeiou]$', 'i');
或者用一个兼容所有长度的简洁正则:
select distinct city from station where regexp_like(city, '^[^aeiou].*[^aeiou]$|^[^aeiou]$', 'i');
这个正则用|(或)同时匹配两种场景:长度≥2的开头结尾非元音城市,以及长度为1的非元音城市。
另外补充一点:Oracle的\w会匹配字母、数字和下划线,如果题目中城市名仅包含字母,用.*就足够,没必要用\w,避免引入不必要的匹配范围。
内容的提问来源于stack exchange,提问作者Teguh Pambudi
相关产品推荐
相关产品推荐

