Oracle多值组

时间:2019-02-20 10:31:51

标签: oracle replace multivalue

我有一个包含2个多值字段的表 例如:

第一行包含以下字段:

字段1:1、4、5

字段2:1、2、3

第二行包含:

字段1:5、6、7

字段2:,6,3

第三行:

字段1:8,,9

字段2:1、3,

|---------------------|------------------|
|      column 1       |     column 2     |
|---------------------|------------------|
|       1,4,5         |       1,2,3      |
|---------------------|------------------|
|       5,6,7         |       ,6,3       |
|---------------------|------------------|
|       8,,9          |        1,,3      |
|---------------------|------------------|

因此两个字段都相关-字段1位置2的值与字段2位置2的值有关。 我要做的是仅在每个组中的值相等的情况下更新/替换字段2中的一个或多个值。

例如  在第一行中,位置0处具有匹配值'1',需要在字段2中进行替换。我该怎么做?只需提及字段1和字段2中的空值不应视为相等,它们只是在显示位置。询问您是否需要更多信息

1 个答案:

答案 0 :(得分:0)

首先,不要使用它;而是将表格设计固定为不存储逗号分隔的值。但是,如果您坚持要求,则可以使用此方法将csv拆分为单个值,然后执行替换,然后再次对其进行汇总,并使用Body语句来更新与MERGE伪列上的更新相关的表

Oracle设置

ROWID

执行替换

这会将每个CREATE TABLE test_data ( column1 VARCHAR2(20), column2 VARCHAR2(20) ); INSERT INTO test_data ( column1, column2 ) SELECT '1,4,5', '1,2,3' FROM DUAL UNION ALL SELECT '5,6,7', ',6,3' FROM DUAL UNION ALL SELECT '8,,9', '1,,3' FROM DUAL UNION ALL SELECT '1,4,5', '3,4,5' FROM DUAL; 匹配column2的值加10。

column1

输出

MERGE INTO test_data dst
USING ( 
  SELECT rid,
         REPLACE(
           LISTAGG(
             COALESCE( TO_CHAR( column1 ), '#' ),
             ','
           ) WITHIN GROUP ( ORDER BY idx ),
           '#'
         )AS column1,
         REPLACE(
           LISTAGG(
             COALESCE( TO_CHAR( CASE column2 WHEN column1 THEN column2 + 10 ELSE column2 END ), '#' ),
             ','
           ) WITHIN GROUP ( ORDER BY idx ),
           '#'
         ) AS column2
  FROM   (
    SELECT t.ROWID AS rid,
           COLUMN_VALUE AS idx,
           TO_NUMBER( REGEXP_SUBSTR( t.column1, '(\d*)(,|$)', 1, COLUMN_VALUE, NULL, 1 ) ) AS column1,
           TO_NUMBER( REGEXP_SUBSTR( t.column2, '(\d*)(,|$)', 1, COLUMN_VALUE, NULL, 1 ) ) AS column2
    FROM   test_data t
           CROSS JOIN
           TABLE(
             CAST(
               MULTISET(
                 SELECT LEVEL
                 FROM   DUAL
                 CONNECT BY LEVEL < REGEXP_COUNT( t.column1, '(\d*)(,|$)' )
               )
               AS SYS.ODCINUMBERLIST
             )
           ) l
  )
  GROUP BY rid
) src
ON ( dst.ROWID = src.RID )
WHEN MATCHED THEN
  UPDATE SET column2 = src.column2 WHERE src.column2 <> dst.column2;
COLUMN1 | COLUMN2
:------ | :------
1,4,5   | 11,2,3 
5,6,7   | ,16,3  
8,,9    | 1,,3   
1,4,5   | 3,14,15

db <>提琴here