将分隔的单元格记录拆分为行性能

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 逻辑,并且每分钟都后悔我必须处理这些东西。

以上是关于将分隔的单元格记录拆分为行性能的主要内容,如果未能解决你的问题,请参考以下文章

如何在excel中拆分单元格

将 pandas 中的一个单元格拆分为多行

读取 df,拆分每个单元格并附加到列表

关于Excle表格如何拆分?

如何将EXCEL表格中的同一列有相同的内容 合并成一个单元格?

java如何解析excel一个单元格中逗号分隔的数据