将“regexp_substr”(Oracle)转换为 PostgreSQL

Cat*_*adu 6 oracle postgresql rownum regexp-substr

我在 Oracle SQL 中有这样的查询:

       select town_name, 
              regexp_substr(town_name, '[^A,]+', 1, 1) as c1,
              regexp_substr(town_name, '[^A,]+', 1, 2) as c2, 
              regexp_substr(town_name, '[^A,]+', 1, rownum) as c_rownum,
              rownum
          from epr_towns
Run Code Online (Sandbox Code Playgroud)

结果的前 2 行是:

VALGANNA        V   LG  V   1
VARANO BORGHI   V   R   R   2
Run Code Online (Sandbox Code Playgroud)

我需要在 PostgreSQL 上获得相同的结果(对于带有 的行regexp_substr(town_name, '[^A,]+', 1, rownum) as c_rownum),但我不知道如何实现。你可以帮帮我吗?谢谢。

wrs*_*der 7

这里确实有两个不同的问题

  • 替换行号
  • 将 regexp_substr 替换为 regexp_matches

要求解 rownum,请使用 CTE (WITH子句) 将类似 rownum 的列添加到基础表中。

regexp_matches与 Oracle 的工作方式略有不同regexp_substr。Oracleregexp_substr将第 n 个匹配作为参数,而 PostgreSQL会将所有匹配作为表值函数regexp_matches返回。因此,您必须将调用包装在带有限制/偏移量的子查询中,以提取第 n 个匹配项。此外,返回的行是数组,因此假设您的正则表达式中没有括号表达式,您需要索引/取消引用数组中的第一项。regexp_substr

最终结果如下所示:

http://sqlfiddle.com/#!17/865ee/7

 with epr_towns_rn as (
    select town_name,
      row_number() over(order by town_name) as rn
  from epr_towns
)
select town_name,
   (select (regexp_matches(town_name, '[^A,]+', 'g'))[1] offset 0 limit 1) as c1,
   (select (regexp_matches(town_name, '[^A,]+', 'g'))[1] offset 1 limit 1) as c2,
   (select (regexp_matches(town_name, '[^A,]+', 'g'))[1] offset rn-1 limit 1)
     as c_rownum,
   rn
   from epr_towns_rn;
Run Code Online (Sandbox Code Playgroud)

如果您只想要第一个匹配项,则可以省略 'g' 参数并省略子查询的限制/偏移量,但您仍然需要子查询包装器,以防不匹配,以模仿 regexp_substr 在不匹配时返回 null。


Vao*_*sun 1

我没有表,所以我使用生成例如:

   select town_name, 
          regexp_substr(town_name, '[^A,]+', 1, 1) as c1,
          regexp_substr(town_name, '[^A,]+', 1, 2) as c2, 
          regexp_substr(town_name, '[^A,]+', 1, dense_rank() over (order by town_name)) as c_rownum,
          dense_rank() over (order by c)
      from epr_towns
Run Code Online (Sandbox Code Playgroud)

我相信您正在寻找dense_rank窗口函数?..

注意。拥有 SQL 小提琴或初始代码总是更容易