5

我在 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

结果的前 2 行是:

VALGANNA        V   LG  V   1
VARANO BORGHI   V   R   R   2

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

4

3 回答 3

7

这里真的有两个不同的问题

  • 替换rownum
  • 用 regexp_matches 替换 regexp_substr

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

regexp_matches工作方式与 Oracle 略有不同regexp_substr。Oracleregexp_substr将第 n 个匹配项作为参数,而 PostgreSQLregexp_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;

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

于 2018-07-05T14:28:23.417 回答
1

我没有桌子,所以我使用 generate 例如:

   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

我相信你在寻找dense_rank 窗口函数?

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

于 2015-08-18T12:06:22.207 回答
0

您可以在此页面上找到您的案例和其他场景: https ://pgxn.org/dist/orafce/doc/sql_migration/sql_migration03.html

--

简而言之,您可以这样做:从 OracleDB:

SELECT
    REGEXP_SUBSTR('one two three four five ',
    '(\S*)\s') AS "REGEXP"
FROM DUAL;

结果:一

到 PostgreSQL:

SELECT (
    SELECT array_to_string(a, '') AS "REGEXP"
    FROM regexp_matches('one two three four five ',
    '(\S*)\s',
    'g') AS f(a)
    LIMIT 1
);

结果:一

于 2021-08-12T07:51:38.537 回答