将分隔的单元格记录拆分为行性能
Posted
技术标签:
【中文标题】将分隔的单元格记录拆分为行性能【英文标题】:Split Delimited Cell Record Into Rows Performance 【发布时间】:2019-08-26 08:34:30 【问题描述】:我有 2 列
COLUMN1 || COLUMN2
15 || 23|45|65|44|66|15
34 || 45|21|16|34|79
我想将COLUMN2
区分为行,并与$0:15$1:23$1:45$1:65$1:44$1:66
等一些特殊语法合并。为了解决这个问题,这里有 2 个解决方案
-
我可以将级别分开,例如
SELECT COLUMN1,COLUMN2, REGEXP_SUBSTR(COLUMN2,'[^|]\d+',1,LEVEL)
FROM TABLE_NAME
CONNECT BY REGEXP_SUBSTR(COLUMN2,'[^|]\d+',1,LEVEL) IS NOT NULL
-
我可以将
COLUMN2
与其他列分开并将其合并回来。但这会产生大量的regexp_substr
功能。
问题就在这里,我对性能有巨大的影响。花了这么长时间。我正在寻找更有效的方法来做到这一点。行数超过1M
。
编辑 1:
COLUMN1 将以$0:
开头,如果 COLUMN2 的分隔值相同,则不会在结果中考虑。
预期输出:
$0:15$1:23$1:45$1:65$1:44$1:66
$0:34$1:45$1:21$1:16$1:79
注意 Column1 不能是 column2 的第一个元素
【问题讨论】:
“我正在寻找更有效的方法。” 因为所有方法都需要扫描 FULL 表,所以很明显你应该规范化.. 这个问题确实比较复杂。实际上分成行是必须的,因为可能需要区分 2,3 行并将其合并到一行中。我正在使用full parallel(8)
提示来提高性能。我以简单的方式问了这个问题,以获得一些简单的想法。现在我正在我的环境中发展你的想法。非常感谢@RaymondNijland
【参考方案1】:
我可能错了,但它看起来像一个简单的替换案例,如下所示:
SELECT '$0:' || REPLACE('23|45|65|44|66','|',' $1:') FROM DUAL;
如果您需要其他任何内容,请发表评论。
-- 更新--
根据问题中添加的附加条件,您现在可以尝试:
SQL> WITH MY_TAB(COL1,COL2)
2 AS (
3 SELECT 15, '23|45|65|44|66|15' FROM DUAL UNION ALL
4 SELECT 34, '45|21|16|34|79' FROM DUAL
5 )SELECT
6 '$0:'
7 || COL1
8 || '$1:'
9 || REPLACE(REPLACE(COL2, '|' || COL1, ''), '|', '$1:') AS DESIRED_VALUE
10 FROM
11 MY_TAB;
DESIRED_VALUE
--------------------------------------------------------------------------------
$0:15$1:23$1:45$1:65$1:44$1:66
$0:34$1:45$1:21$1:16$1:79
SQL>
干杯!!
【讨论】:
观点不错,但有一些条件,问题忘了说,我补充了。 请也添加预期的输出 添加了预期输出 如果 COL1 是 col2 的 csv 列表中的第一个值,这将不起作用。【参考方案2】:您可以使用以下语法来生成您的预期结果:
RTRIM('$0'|| column1 ||
REPLACE( '$1:' || REPLACE(column2,'|',' $1:') || '$'
, '$1:'||column1||'$'
, '$')
,'$')
您还可以使用递归查询代替原来的查询,这样可以消除重复的行:
WITH TABLE_NAME (column1, column2) AS (
select 15 , '23|45|65|44|66' from dual UNION all
select 34 , '45|21|16|95|79' from dual)
, rec (column1, pos, col2, column2) AS (
SELECT column1, 1, REGEXP_SUBSTR(COLUMN2,'\d+'), column2 FROM table_name
UNION ALL
SELECT column1, pos + 1, REGEXP_SUBSTR(COLUMN2,'\d+',1,pos + 1), column2
FROM rec
WHERE REGEXP_SUBSTR(COLUMN2,'\d+',1,pos + 1) IS NOT NULL )
SELECT * FROM rec
我建议创建一个新表并在那里拆分 csv 列以获得更好的数据模型,然后对该数据执行所有操作会更容易。处理 csv 数据总是一团糟。
【讨论】:
目前在我们的数据模型中创建新表不是正确的方法,正如我在问题中提到的正则表达式会产生巨大的性能影响。我是说,你的递归查询。但第一个也是解决问题。谢谢 您可以使用视图来模仿旧数据模型,无需更改当前逻辑,然后可以逐个替换逻辑。但这只是一些建议,我自己在应用程序中有 csv 逻辑,并且每分钟都后悔我必须处理这些东西。以上是关于将分隔的单元格记录拆分为行性能的主要内容,如果未能解决你的问题,请参考以下文章