获取子字符串之前的字符串,直到字符的第 n 次出现

Get String Before a Substring till nth Occurrences of a Character

我正在处理一个字符串,我试图在出现任何子字符串“1:”之前获取一个字符串,直到出现 3 次字符“<”和出现 3 次字符“>”。

以下是字符串:

<Affected Items.Lifecycle Phase>WAS<Items.Active>IS<Items.Obsolete>1:<対象アイテム.ライフサイクル フェーズ> は <アイテム.Active> から <アイテム.破棄> に変更されました。2:<受影響的項目.生命週期階段>原為<物料.Active>現為<物料.報廢>3:<Données techniques affectées.Phase de cycle de vie>ÉTAIT<Données techniques.Active>EST<Données techniques.Obsolète>4:<受影响的物件.生命周期阶段>原为<物件.Active>现为<物件.报废>5:<Betroffene Artikel.Lebenszyklusphase>WAR<Artikel.Active>IST<Artikel.Veraltet>6:<영향 받은 항목.수명 주기 단계>기존:<항목.Active>현재:<항목.폐기>7:<Задействованные элементы.Фаза жизненного цикла>ЯВЛЯЛСЯ<Элементы.Active>ЯВЛЯЕТСЯ<Элементы.Устарело>; <Affected Items.New Rev>WAS<>IS<1>1:<対象アイテム.新規リビジョン> は <> から <1> に変更されました。2:<受影響的項目.新版本>原為<>現為<1>3:<Données techniques affectées.Nouvelle révision>ÉTAIT<>EST<1>4:<受影响的物件.新版本>原为<>现为<1>5:<Betroffene Artikel.Neue Revision>WAR<>IST<1>6:<영향 받은 항목.새 수정 버전>기존:<>현재:<1>7:<Задействованные элементы.Новая ред.>ЯВЛЯЛСЯ<>ЯВЛЯЕТСЯ<1>

我想要以下子串:

<Affected Items.Lifecycle Phase>WAS<Items.Active>IS<Items.Obsolete>

<Affected Items.New Rev>WAS<>IS<1>

我可以使用下面的 SQL 获取第一个子字符串。但是很难得到第二个。

WITH CTE AS
(
SELECT '<Affected Items.Lifecycle Phase>WAS<Items.Active>IS<Items.Obsolete>1:<対象アイテム.ライフサイクル フェーズ> は <アイテム.Active> から <アイテム.破棄> に変更されました。2:<受影響的項目.生命週期階段>原為<物料.Active>現為<物料.報廢>3:<Données techniques affectées.Phase de cycle de vie>ÉTAIT<Données techniques.Active>EST<Données techniques.Obsolète>4:<受影响的物件.生命周期阶段>原为<物件.Active>现为<物件.报废>5:<Betroffene Artikel.Lebenszyklusphase>WAR<Artikel.Active>IST<Artikel.Veraltet>6:<영향 받은 항목.수명 주기 단계>기존:<항목.Active>현재:<항목.폐기>7:<Задействованные элементы.Фаза жизненного цикла>ЯВЛЯЛСЯ<Элементы.Active>ЯВЛЯЕТСЯ<Элементы.Устарело>; <Affected Items.New Rev>WAS<>IS<1>1:<対象アイテム.新規リビジョン> は <> から <1> に変更されました。2:<受影響的項目.新版本>原為<>現為<1>3:<Données techniques affectées.Nouvelle révision>ÉTAIT<>EST<1>4:<受影响的物件.新版本>原为<>现为<1>5:<Betroffene Artikel.Neue Revision>WAR<>IST<1>6:<영향 받은 항목.새 수정 버전>기존:<>현재:<1>7:<Задействованные элементы.Новая ред.>ЯВЛЯЛСЯ<>ЯВЛЯЕТСЯ<1>'
AS "DETAILS"
FROM DUAL
)
select "DETAILS",
     CASE
          WHEN "DETAILS" != CONVERT ("DETAILS", 'US7ASCII')
            THEN
              CASE WHEN "DETAILS" LIKE '%1:%'
                THEN
               SUBSTR("DETAILS", 0, INSTR("DETAILS", '1:')-1)
               ELSE
                 REGEXP_REPLACE ("DETAILS", '[^ -~]', '')
                 END
             else
               "DETAILS" end as details

FROM CTE 

如有任何帮助,我们将不胜感激!

本文:https://blogs.oracle.com/sql/post/split-comma-separated-values-into-rows-in-oracle-database

解释了如何将 comma-separated 值字符串拆分成行。

因此,我们可以使用 <Affected Items. 作为分隔符。

这样做我们可以将这些行插入到临时 table 中,或者围绕它们进行查询,使用这个想法作为子字符串并提取每行的有价值部分,即从一开始直到第一次出现 :.

我给出的link提供了这个例子:

with rws as (
  select 'split,into,rows' str from dual
)
  select regexp_substr (
           str,
           '[^,]+',
           1,
           level
         ) value
  from   rws
  connect by level <= 
    length ( str ) - length ( replace ( str, ',' ) ) + 1;
    
VALUE   
split    
into     
rows

并提供以下解释:

因此,如果您将 <Affected Items. 视为您的分隔符(而不是 ,)并且生成行,则每一行都将包含有用的信息,直到它的第一个 : .最后,您需要在结果前添加分隔符。

您可以使用:

WITH split (details, match, end_pos) AS (
  SELECT details,
         REGEXP_SUBSTR(details, '(.*?)\d+:', 1, 1, NULL, 1),
         REGEXP_INSTR(details, '(.*?)\d+:', 1, 1, 1)
  FROM   table_name
UNION ALL
  SELECT details,
         REGEXP_SUBSTR(details, '(.*?)\d+:', end_pos, 1, NULL, 1),
         REGEXP_INSTR(details, '(.*?)\d+:', end_pos, 1, 1)
  FROM   split
  WHERE  end_pos > 0
),
brackets (match, opening, closing) AS (
  SELECT match,
         INSTR(match, '<', -1, 3),
         INSTR(match, '>', -1, 3)
  FROM   split
  WHERE  end_pos > 0
),
last_3_brackets (match) AS (
  SELECT SUBSTR(match, LEAST(opening, closing)) AS match
  FROM   brackets
  WHERE  opening > 0
  AND    closing > 0
)
SELECT *
FROM   last_3_brackets
WHERE  match = CONVERT (match, 'US7ASCII')

其中,对于示例数据:

CREATE TABLE table_name (details) AS
SELECT '<Affected Items.Lifecycle Phase>WAS<Items.Active>IS<Items.Obsolete>1:<対象アイテム.ライフサイクル フェーズ> は <アイテム.Active> から <アイテム.破棄> に変更されました。2:<受影響的項目.生命週期階段>原為<物料.Active>現為<物料.報廢>3:<Données techniques affectées.Phase de cycle de vie>ÉTAIT<Données techniques.Active>EST<Données techniques.Obsolète>4:<受影响的物件.生命周期阶段>原为<物件.Active>现为<物件.报废>5:<Betroffene Artikel.Lebenszyklusphase>WAR<Artikel.Active>IST<Artikel.Veraltet>6:<영향 받은 항목.수명 주기 단계>기존:<항목.Active>현재:<항목.폐기>7:<Задействованные элементы.Фаза жизненного цикла>ЯВЛЯЛСЯ<Элементы.Active>ЯВЛЯЕТСЯ<Элементы.Устарело>; <Affected Items.New Rev>WAS<>IS<1>1:<対象アイテム.新規リビジョン> は <> から <1> に変更されました。2:<受影響的項目.新版本>原為<>現為<1>3:<Données techniques affectées.Nouvelle révision>ÉTAIT<>EST<1>4:<受影响的物件.新版本>原为<>现为<1>5:<Betroffene Artikel.Neue Revision>WAR<>IST<1>6:<영향 받은 항목.새 수정 버전>기존:<>현재:<1>7:<Задействованные элементы.Новая ред.>ЯВЛЯЛСЯ<>ЯВЛЯЕТСЯ<1>' FROM DUAL;

输出:

MATCH
<Affected Items.Lifecycle Phase>WAS<Items.Active>IS<Items.Obsolete>
<Betroffene Artikel.Lebenszyklusphase>WAR<Artikel.Active>IST<Artikel.Veraltet>
<Affected Items.New Rev>WAS<>IS<1>
<Betroffene Artikel.Neue Revision>WAR<>IST<1>

db<>fiddle here