如何从两列之间的差异创建新列?
Posted
技术标签:
【中文标题】如何从两列之间的差异创建新列?【英文标题】:how to create new column from difference between two columns? 【发布时间】:2020-05-15 09:49:58 【问题描述】:我使用 join、listagg 等创建新表。我使用 listagg 函数确定了如下两列。该列包含以下信息。
Listagg_1_Column | Listagg_2_Column
---------------- |-----------------
123,234,565,321 | 123,234
我想在此表中添加新列。新列包含 Listagg_1_Column 和 Listagg_2_Column 之间的差异,如下所示
New_Column
----------
565,321
为此,我使用了replace(Listagg_1_Column,Listagg_2_Column,'')
语句,但我检索到了错误的结果。如何通过更改查询来获取新列?任何帮助将不胜感激。提前致谢。
【问题讨论】:
比较 listagg 数据真的是解决您业务问题的最佳选择吗?创建一个只有前 2 个 listagg 列的数据集相交的第三个 listagg 列不是更容易吗?不确定该选项在您的情况下是否可行,但肯定会是一个更像“sql”的答案...... 您可以在查询中使用条件逻辑执行此操作,但您没有提供足够的信息来了解是否是这种情况。 我得到了我想要的结果。首先,我将其分为两部分,主要查询和两列之间的差异通过使用减法函数进行过滤。对找到的数据使用listagg函数,检索数据效果很好。 Koen Lostrie 的评论启发了我。感谢他的宝贵意见。 【参考方案1】:我有测试数据:
CREATE TABLE data ( col1, col2 ) AS
SELECT '123,234,565,321', '123,234' FROM DUAL UNION ALL
SELECT '123,234,1123,2345', '123,234' FROM DUAL UNION ALL
SELECT '123,565,321,234', '123,234' FROM DUAL
然后您可以使用XMLTABLE
拆分字符串并使用MINUS
查找两组之间的差异并将结果整理到一个集合中,然后您可以聚合该集合:
SELECT col1,
col2,
( SELECT LISTAGG( column_value, ',' ) WITHIN GROUP ( ORDER BY column_value )
FROM TABLE( d.new_col )
) AS new_col
FROM (
SELECT col1,
col2,
CAST(
MULTISET(
( SELECT TO_NUMBER( column_value )
FROM XMLTABLE( ('"' || REPLACE( d.col1, ',', '","' ) || '"') )
MINUS
SELECT TO_NUMBER( column_value )
FROM XMLTABLE( ('"' || REPLACE( d.col2, ',', '","' ) || '"') )
)
) AS SYS.ODCINUMBERLIST
) AS new_col
FROM data d
) d;
哪些输出:
COL1 | COL2 | NEW_COL :---------------- | :-------- | :-------- 123,234,565,321 | 123,234 | 321,565 123,234,1123,2345 | 123,234 | 1123,2345 123,565,321,234 | 123,234 | 321,565
db小提琴here
【讨论】:
【参考方案2】:在这里我将两列转换为两个表。之后很容易找到差异。
with xxx
as (select '123,565,321,234' listagg_1_column,
'123,234' listagg_2_column
from DUAL)
select listagg_1_column,
listagg_2_column,
LISTAGG (myrow, ',') within group (order by myrow) diff
from ( select REGEXP_SUBSTR (listagg_1_column,
'[^,]+',
1,
LEVEL)
myrow,
listagg_1_column,
listagg_2_column
from xxx
connect by REGEXP_SUBSTR (listagg_1_column,
'[^,]+',
1,
LEVEL)
is not null) xx
where xx.myrow not in ( select REGEXP_SUBSTR (listagg_2_column,
'[^,]+',
1,
LEVEL)
myrow
from xxx
connect by REGEXP_SUBSTR (listagg_2_column,
'[^,]+',
1,
LEVEL)
is not null)
group by listagg_1_column, listagg_2_column
上面的代码只适用于一个计数。这里是多记录的。
WITH data ( listagg_1_column, listagg_2_column )
AS (SELECT '123,234,565,321',
'123,234'
FROM dual
UNION ALL
SELECT '123,234,1123,2345',
'123,234'
FROM dual
UNION ALL
SELECT '123,565,321,234',
'123,234'
FROM dual
UNION ALL
SELECT '123,565,321,234',
'321,565'
FROM dual)
SELECT listagg_1_column,
listagg_2_column,
Listagg (myrow, ',')
within GROUP (ORDER BY myrow ) diff
FROM (SELECT DISTINCT Regexp_substr (xx.listagg_1_column, '+[^,]+', 1, LEVEL)
myrow,
xx.listagg_1_column,
xx.listagg_2_column,
Regexp_count (listagg_1_column, '[^,]+')
a,
LEVEL
FROM data xx
CONNECT BY Regexp_count (listagg_1_column, '[^,]+') >= LEVEL
ORDER BY listagg_1_column,
LEVEL)xx
WHERE xx.myrow NOT IN (SELECT Regexp_substr (yy.listagg_2_column, '[^,]+', 1,
LEVEL)
myrow
FROM data yy
WHERE XX.listagg_1_column = YY.listagg_1_column
AND XX.listagg_2_column = YY.listagg_2_column
CONNECT BY Regexp_count (yy.listagg_2_column, '[^,]+')
>= LEVEL
)
GROUP BY listagg_1_column,
listagg_2_column
db小提琴here
【讨论】:
这并不总是像你期望的那样工作db<>fiddle。 你是对的。谢谢分享。我想我已经修好了。但我无法解释我该怎么做。我的大脑一片空白。以上是关于如何从两列之间的差异创建新列?的主要内容,如果未能解决你的问题,请参考以下文章