oracle 从多列捕获值并应用修剪和替换

uttx8gqw  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(107)

我想连接来自Oracle中不同列的字符串,但有些列有值,有些没有。我想要的是,如果C1的最后3个字符的值与C2的值的前3个字符匹配,则与破折号(-)连接,然后删除2秒匹配/出现,或者与下划线(_)连接,这3个字符都保留,因此与下一列一起忽略空值。
数据集:

Sno C1      C2      C3      C4
1   ABC-DEF DEF-ABC
2   DEF-ABC XYZ-DEF ABC-DEF
3   XYZ-DEF DEF-ABC ABC-DEF GHI-XYZ

测试结果:

SNo Concatenated_Data
1   ABC-DEF-ABC
2   DEF-ABC_XYZ-DEF_ABC-DEF
3   XYZ-DEF-ABC-DEF_GHI-XYZ

我看到this approach,它连接所有列的值,但下划线不捕获,如果最后3个字符的C1和前3个字符的C2不匹配。任何人都可以更新select语句吗?

SELECT Sno,TRIM(BOTH '-' FROM
     REGEXP_REPLACE(
       REGEXP_REPLACE(
         C1 || '-' || C2 || '-' || C3 || '-' || C4,
         '-{2,}',
         '-'
       ),
       '([^-_]{3})-\1',
       '\1'
     )
   ) AS Concatenated_Data
FROM   t1
oogrdqng

oogrdqng1#

假设你的列将从左边开始填充值,右边有NULL值(而不是两个非NULL值之间的NULL值),那么你可以使用CASE表达式来比较前一项的最后3个字符和当前项的前3个字符,并基于此进行连接:

SELECT sno,
       c1
       || CASE
          WHEN c2 IS NULL
          THEN NULL
          WHEN SUBSTR(c1, -3) = SUBSTR(c2, 1, 3)
          THEN SUBSTR(c2, 4)
          ELSE '_' || c2
          END
       || CASE
          WHEN c3 IS NULL
          THEN NULL
          WHEN SUBSTR(c2, -3) = SUBSTR(c3, 1, 3)
          THEN SUBSTR(c3, 4)
          ELSE '_' || c3
          END
       || CASE
          WHEN c4 IS NULL
          THEN NULL
          WHEN SUBSTR(c3, -3) = SUBSTR(c4, 1, 3)
          THEN SUBSTR(c4, 4)
          ELSE '_' || c4
          END AS combined
FROM   table_name;

其中,对于样本数据:

CREATE TABLE table_name (Sno, C1, C2, C3, C4) AS
SELECT 1, 'ABC-DEF', 'DEF-ABC', NULL,      NULL      FROM DUAL UNION ALL
SELECT 2, 'DEF-ABC', 'XYZ-DEF', 'ABC-DEF', NULL      FROM DUAL UNION ALL
SELECT 3, 'XYZ-DEF', 'DEF-ABC', 'ABC-DEF', 'GHI-XYZ' FROM DUAL;

输出:
| Sno|组合|
| --|--|
| 1 |ABC-DEF-ABC|
| 2 |DEF-ABC_XYZ-DEF_ABC-DEF|
| 3 |XYZ-DEF-ABC-DEF_GHI-XYZ|
你也可以使用正则表达式,它可能类型较少,但可能比简单的字符串函数效率低:

SELECT sno,
       REGEXP_REPLACE(
          c1
          || CASE WHEN c2 IS NULL THEN NULL ELSE '_' || c2 END
          || CASE WHEN c3 IS NULL THEN NULL ELSE '_' || c3 END
          || CASE WHEN c4 IS NULL THEN NULL ELSE '_' || c4 END,
          '([^-_]{3})_\1',
          '\1'
       ) AS combined
FROM   table_name;

其输出相同。
fiddle

相关问题