Oracle 多值组
Oracle multivalue groups
我有一个带有 2 个多值字段的 table
例如:
第 1 行包含以下字段:
字段 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 的值相关。
我想做的是 update/replace 字段 2 中的一个或多个值,只有每个组中的值都相等。
例如
在第一行中,我在位置 0 中有匹配值“1”,需要在字段 2 中替换它。我该怎么做?只需提及字段 1 和字段 2 中的空值不应被视为相等,它们的存在只是为了显示位置。询问您是否需要更多信息
第一,不要用这个;而是修复您的 table 设计,使其不存储逗号分隔值。但是,如果您坚持,那么您可以使用它将 csv 拆分为单独的值,然后执行替换,然后再次聚合它们并使用 MERGE
语句更新 table 与 [= 上的更新相关联14=] 伪列.
Oracle 设置:
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;
执行替换:
这会将 10 添加到每个 column2
匹配 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;
输出:
SELECT * FROM test_data;
COLUMN1 | COLUMN2
:------ | :------
1,4,5 | 11,2,3
5,6,7 | ,16,3
8,,9 | 1,,3
1,4,5 | 3,14,15
db<>fiddle here
我有一个带有 2 个多值字段的 table 例如:
第 1 行包含以下字段:
字段 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 的值相关。 我想做的是 update/replace 字段 2 中的一个或多个值,只有每个组中的值都相等。
例如 在第一行中,我在位置 0 中有匹配值“1”,需要在字段 2 中替换它。我该怎么做?只需提及字段 1 和字段 2 中的空值不应被视为相等,它们的存在只是为了显示位置。询问您是否需要更多信息
第一,不要用这个;而是修复您的 table 设计,使其不存储逗号分隔值。但是,如果您坚持,那么您可以使用它将 csv 拆分为单独的值,然后执行替换,然后再次聚合它们并使用 MERGE
语句更新 table 与 [= 上的更新相关联14=] 伪列.
Oracle 设置:
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;
执行替换:
这会将 10 添加到每个 column2
匹配 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;
输出:
SELECT * FROM test_data;
COLUMN1 | COLUMN2 :------ | :------ 1,4,5 | 11,2,3 5,6,7 | ,16,3 8,,9 | 1,,3 1,4,5 | 3,14,15
db<>fiddle here