将表格的一个字段分开最多5个单独的行,每个记录分隔符字符的每个实例(char(30))

发布于 2025-02-12 08:48:17 字数 997 浏览 0 评论 0原文

我目前正在研究一个Oracle SQL脚本,该脚本需要将下表的地址字段拆分下面的地址字段最多5行。上述字段由记录分离器角色界定(char(30)。我想索要任何建议的方法如何提出上述数据?

请参阅下面的示例数据。


| ID      | ADDRESS                                                |
|;--------|;-------------------------------------------------------|
| 1000000 | Xxxxx XxxxxXxxxx XxxxXxxxxx xx Xxxxxx                |
| 1000001 | 61 Xxxxxxx XxxxXxxxxxxXxxx                           |
| 1000002 | 36 Xxxxx XxxXxxxxxxxxXxxxxxxxxxxxxxXxxxxxxxxxxxxxxx |


上面的样本如下。

| ID      | ADDRESS1        | ADDRESS2   | ADDRESS3         | ADDRESS4         | ADDRESS5|
|;--------|;----------------|;-----------|;-----------------|;-----------------|;--------|
| 1000000 | Xxxxx Xxxxx     | Xxxxx Xxxx | Xxxxxx xx Xxxxxx |                  |         |
| 1000001 | 61 Xxxxxxx Xxxx | Xxxxxxx    | Xxxx             |                  |         |
| 1000002 | 36 Xxxxx Xxx    | Xxxxxxxxx  | Xxxxxxxxxxxxxx   | Xxxxxxxxxxxxxxxx |         |

I am currently working on an Oracle SQL script that needs to split the ADDRESS field of the table below up to 5 separate rows. The said field is delimited by a record separator character (CHAR(30). I would like to ask for any recommended approach how to come up with the said data?

Please see sample data below.

| ID      | ADDRESS                                                |
|;--------|;-------------------------------------------------------|
| 1000000 | Xxxxx XxxxxXxxxx XxxxXxxxxx xx Xxxxxx                |
| 1000001 | 61 Xxxxxxx XxxxXxxxxxxXxxx                           |
| 1000002 | 36 Xxxxx XxxXxxxxxxxxXxxxxxxxxxxxxxXxxxxxxxxxxxxxxx |

The expected output of the sample above is as follows.

| ID      | ADDRESS1        | ADDRESS2   | ADDRESS3         | ADDRESS4         | ADDRESS5|
|;--------|;----------------|;-----------|;-----------------|;-----------------|;--------|
| 1000000 | Xxxxx Xxxxx     | Xxxxx Xxxx | Xxxxxx xx Xxxxxx |                  |         |
| 1000001 | 61 Xxxxxxx Xxxx | Xxxxxxx    | Xxxx             |                  |         |
| 1000002 | 36 Xxxxx Xxx    | Xxxxxxxxx  | Xxxxxxxxxxxxxx   | Xxxxxxxxxxxxxxxx |         |

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清晨说晚安 2025-02-19 08:48:17

这是一个选项:

SQL> with test (id, address) as
  2    (select 1000000, 'Xxxxx Xxxxx^^Xxxxx Xxxx^^Xxxxxx xx Xxxxxx' from dual union all
  3     select 1000002, '36 Xxxxx Xxx^^Xxxxxxxxx^^Xxxxxxxxxxxxxx^^Xxxxxxxxxxxxxxxx' from dual
  4    )
  5  select id, regexp_substr(address, '[^' ||chr(30) ||']+', 1, 1) val1,
  6             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 2) val2,
  7             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 3) val3,
  8             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 4) val4,
  9             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 5) val5
 10  from test;

        ID VAL1                 VAL2                 VAL3                 VAL4                 VAL5
---------- -------------------- -------------------- -------------------- -------------------- --------------------
   1000000 Xxxxx Xxxxx          Xxxxx Xxxx           Xxxxxx xx Xxxxxx
   1000002 36 Xxxxx Xxx         Xxxxxxxxx            Xxxxxxxxxxxxxx       Xxxxxxxxxxxxxxxx

SQL>

Here's one option:

SQL> with test (id, address) as
  2    (select 1000000, 'Xxxxx Xxxxx^^Xxxxx Xxxx^^Xxxxxx xx Xxxxxx' from dual union all
  3     select 1000002, '36 Xxxxx Xxx^^Xxxxxxxxx^^Xxxxxxxxxxxxxx^^Xxxxxxxxxxxxxxxx' from dual
  4    )
  5  select id, regexp_substr(address, '[^' ||chr(30) ||']+', 1, 1) val1,
  6             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 2) val2,
  7             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 3) val3,
  8             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 4) val4,
  9             regexp_substr(address, '[^' ||chr(30) ||']+', 1, 5) val5
 10  from test;

        ID VAL1                 VAL2                 VAL3                 VAL4                 VAL5
---------- -------------------- -------------------- -------------------- -------------------- --------------------
   1000000 Xxxxx Xxxxx          Xxxxx Xxxx           Xxxxxx xx Xxxxxx
   1000002 36 Xxxxx Xxx         Xxxxxxxxx            Xxxxxxxxxxxxxx       Xxxxxxxxxxxxxxxx

SQL>
画▽骨i 2025-02-19 08:48:17

您可以使用简单的字符串函数(比正则表达式快的数量级):

SELECT id,
       CASE sep1
       WHEN 0 THEN address
       ELSE        SUBSTR(address, 1, sep1 - 1)
       END AS address1,
       CASE 
       WHEN sep1 = 0 THEN NULL
       WHEN sep2 = 0 THEN SUBSTR(address, sep1 + 1)
       ELSE               SUBSTR(address, sep1 + 1, sep2 - sep1 - 1)
       END AS address2,
       CASE 
       WHEN sep2 = 0 THEN NULL
       WHEN sep3 = 0 THEN SUBSTR(address, sep2 + 1)
       ELSE               SUBSTR(address, sep2 + 1, sep3 - sep2 - 1)
       END AS address3,
       CASE 
       WHEN sep3 = 0 THEN NULL
       WHEN sep4 = 0 THEN SUBSTR(address, sep3 + 1)
       ELSE               SUBSTR(address, sep3 + 1, sep4 - sep3 - 1)
       END AS address4,
       CASE 
       WHEN sep4 = 0 THEN NULL
       ELSE               SUBSTR(address, sep4 + 1)
       END AS address5
FROM   (
  SELECT id,
         address,
         INSTR(address, CHR(30), 1, 1) AS sep1,
         INSTR(address, CHR(30), 1, 2) AS sep2,
         INSTR(address, CHR(30), 1, 3) AS sep3,
         INSTR(address, CHR(30), 1, 4) AS sep4
  FROM   table_name
)

对于示例数据:

CREATE TABLE table_name (ID, ADDRESS) AS
SELECT 1000000, 'Xxxxx Xxxxx'||CHR(30)||'Xxxxx Xxxx'||CHR(30)||'Xxxxxx xx Xxxxxx' FROM DUAL UNION ALL
SELECT 1000001, '61 Xxxxxxx Xxxx'||CHR(30)||'Xxxxxxx'||CHR(30)||'Xxxx' FROM DUAL UNION ALL
SELECT 1000002, '36 Xxxxx Xxx'||CHR(30)||'Xxxxxxxxx'||CHR(30)||'Xxxxxxxxxxxxxx'||CHR(30)||'Xxxxxxxxxxxxxxxx' FROM DUAL UNION ALL
SELECT 1000003, 'ABC'||CHR(30)||CHR(30)||CHR(30)||'DEF'||CHR(30)||'HIJ' FROM DUAL;

输出:

idaddress1address2address3address4address5
1000000xxxxx xxxxxxxxxx xxxxxxxxxx xx xxxxxxnullnull
100000161 xxxxxxx xxxxxxxxxxxxxxxnullnull
100000236 xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxnull
1000003abcnullnulldefhij

If you did want to use (slower) regular expressions then:

SELECT id,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 1, NULL, 1 ) AS address1,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 2, NULL, 1 ) AS address2,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 3, NULL, 1 ) AS address3,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 4, NULL, 1 ) AS address4,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 5, NULL, 1 ) AS address5
FROM   table_name

Which outputs the same 。

db<>>

You can use simple string functions (which are an order of magnitude faster than regular expressions):

SELECT id,
       CASE sep1
       WHEN 0 THEN address
       ELSE        SUBSTR(address, 1, sep1 - 1)
       END AS address1,
       CASE 
       WHEN sep1 = 0 THEN NULL
       WHEN sep2 = 0 THEN SUBSTR(address, sep1 + 1)
       ELSE               SUBSTR(address, sep1 + 1, sep2 - sep1 - 1)
       END AS address2,
       CASE 
       WHEN sep2 = 0 THEN NULL
       WHEN sep3 = 0 THEN SUBSTR(address, sep2 + 1)
       ELSE               SUBSTR(address, sep2 + 1, sep3 - sep2 - 1)
       END AS address3,
       CASE 
       WHEN sep3 = 0 THEN NULL
       WHEN sep4 = 0 THEN SUBSTR(address, sep3 + 1)
       ELSE               SUBSTR(address, sep3 + 1, sep4 - sep3 - 1)
       END AS address4,
       CASE 
       WHEN sep4 = 0 THEN NULL
       ELSE               SUBSTR(address, sep4 + 1)
       END AS address5
FROM   (
  SELECT id,
         address,
         INSTR(address, CHR(30), 1, 1) AS sep1,
         INSTR(address, CHR(30), 1, 2) AS sep2,
         INSTR(address, CHR(30), 1, 3) AS sep3,
         INSTR(address, CHR(30), 1, 4) AS sep4
  FROM   table_name
)

Which, for the sample data:

CREATE TABLE table_name (ID, ADDRESS) AS
SELECT 1000000, 'Xxxxx Xxxxx'||CHR(30)||'Xxxxx Xxxx'||CHR(30)||'Xxxxxx xx Xxxxxx' FROM DUAL UNION ALL
SELECT 1000001, '61 Xxxxxxx Xxxx'||CHR(30)||'Xxxxxxx'||CHR(30)||'Xxxx' FROM DUAL UNION ALL
SELECT 1000002, '36 Xxxxx Xxx'||CHR(30)||'Xxxxxxxxx'||CHR(30)||'Xxxxxxxxxxxxxx'||CHR(30)||'Xxxxxxxxxxxxxxxx' FROM DUAL UNION ALL
SELECT 1000003, 'ABC'||CHR(30)||CHR(30)||CHR(30)||'DEF'||CHR(30)||'HIJ' FROM DUAL;

Outputs:

IDADDRESS1ADDRESS2ADDRESS3ADDRESS4ADDRESS5
1000000Xxxxx XxxxxXxxxx XxxxXxxxxx xx Xxxxxxnullnull
100000161 Xxxxxxx XxxxXxxxxxxXxxxnullnull
100000236 Xxxxx XxxXxxxxxxxxXxxxxxxxxxxxxxXxxxxxxxxxxxxxxxnull
1000003ABCnullnullDEFHIJ

If you did want to use (slower) regular expressions then:

SELECT id,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 1, NULL, 1 ) AS address1,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 2, NULL, 1 ) AS address2,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 3, NULL, 1 ) AS address3,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 4, NULL, 1 ) AS address4,
       REGEXP_SUBSTR(address, '(.*?)('|| CHR(30) || '|$)', 1, 5, NULL, 1 ) AS address5
FROM   table_name

Which outputs the same.

db<>fiddle here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文