[英]How to get ids which does not exist in another listagg | Oracle 19c |
I have written a query to get values in comma separated format from both the table我编写了一个查询以从两个表中获取逗号分隔格式的值
Table 1:表格1:
SELECT
regex_replace(xmlcast(Xmlagg(XMLELEMENT(empid, empid, ',')) AS clob), '\s*,\s*$', '') AS str1
FROM
(SELECT empid
FROM employee);
Table 2:表 2:
SELECT
regex_replace(xmlcast(Xmlagg(XMLELEMENT(depid, depid, ',')) AS clob), '\s*,\s*$', '') AS str2
FROM
(SELECT depid
FROM department);
Output of both queries:两个查询的 Output:
str1 = 1,4,5,6,8
str2 = 1,5,6
How do I compare both the str1
and str2
and get ids which are in str1
but not in str2
如何比较str1
和str2
并获取在str1
但不在str2
中的 id
Expected output: 4,8
预期 output: 4,8
You do not need to compare the delimited strings, you can simply use NOT IN
(or NOT EXISTS
) and compare the table values:您不需要比较分隔字符串,您可以简单地使用NOT IN
(或NOT EXISTS
)并比较表值:
SELECT regexp_replace( xmlcast(Xmlagg(XMLELEMENT(empid,empid,',')) as clob),'\s*,\s*$','') AS str1
FROM employee
WHERE empid NOT IN (
SELECT depid
FROM department
);
However, you should consider whether it makes sense to compare the IDs for employees to the IDs for departments as that does not appear to make logical sense.但是,您应该考虑将员工的 ID 与部门的 ID 进行比较是否有意义,因为这似乎没有逻辑意义。
For the sample data:对于样本数据:
CREATE TABLE employee (empid) AS
SELECT 1 FROM DUAL UNION ALL
SELECT 4 FROM DUAL UNION ALL
SELECT 5 FROM DUAL UNION ALL
SELECT 6 FROM DUAL UNION ALL
SELECT 8 FROM DUAL;
CREATE TABLE department (depid) AS
SELECT 1 FROM DUAL UNION ALL
SELECT 5 FROM DUAL UNION ALL
SELECT 6 FROM DUAL;
The query outputs:查询输出:
STR1 STR1 4,8 4,8
Another approach considering that both str1
and str2
are coming from different tables.考虑到str1
和str2
都来自不同的表的另一种方法。 Although I consider the comments more than right that this kind of comparison should not be done this way.尽管我认为这些评论是正确的,但这种比较不应该以这种方式进行。
with x as
(
select regexp_substr(x.str1,'[^,]+',1,level) as str1_spit
from ( select '1,4,5,6,8' as str1 from dual ) x
CONNECT BY LEVEL <=REGEXP_COUNT(x.str1 ,'[,]') + 1
),
y as
( select regexp_substr(y.str2,'[^,]+',1,level) as str2_spit
from ( select '1,5,6' as str2 from dual ) y
CONNECT BY LEVEL <=REGEXP_COUNT(y.str2 ,'[,]') + 1
)
select LISTAGG(str1_spit, ',') WITHIN GROUP (order by str1_spit) as final_value
from
(
select x.str1_spit , y.str2_spit
from x left join y on x.str1_spit = y.str2_spit
where y.str2_spit is null
order by x.str1_spit
)
Demo演示
SQL> with x as
2 (
select regexp_substr(x.str1,'[^,]+',1,level) as str1_spit
from ( select '1,4,5,6,8' as str1 from dual ) x
CONNECT BY LEVEL <=REGEXP_COUNT(x.str1 ,'[,]') + 1
),
y as
( select regexp_substr(y.str2,'[^,]+',1,level) as str2_spit
from ( select '1,5,6' as str2 from dual ) y
CONNECT BY LEVEL <=REGEXP_COUNT(y.str2 ,'[,]') + 1
)
select LISTAGG(str1_spit, ',') WITHIN GROUP (order by str1_spit) as final_value
from
(
select x.str1_spit , y.str2_spit
from x left join y on x.str1_spit = y.str2_spit
where y.str2_spit is null
order by x.str1_spit
) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ;
FINAL_VALUE
--------------------------------------------------------------------------------
4,8
SQL>
If you must do it by comparing strings (don't, use NOT IN
or NOT EXISTS
and compare the tables) then you can do it by only splitting one of the two strings and using simple string functions (rather than regular expressions, which are an order-of-magnitude slower):如果您必须通过比较字符串来做到这一点(不要,使用NOT IN
或NOT EXISTS
并比较表),那么您可以通过仅拆分两个字符串之一并使用简单的字符串函数(而不是正则表达式,它们是慢一个数量级):
WITH data (str1, str2) AS (
SELECT TO_CLOB('1,4,5,6,8'),
TO_CLOB('1,5,6')
FROM DUAL
),
bounds (str1, str2, spos, epos) AS (
SELECT str1,
str2,
1,
INSTR(str1, ',', 1)
FROM data
UNION ALL
SELECT str1,
str2,
epos + 1,
INSTR(str1, ',', epos + 1)
FROM bounds
WHERE epos > 0
),
items (item, str2) AS (
SELECT CASE epos
WHEN 0
THEN SUBSTR(str1, spos)
ELSE SUBSTR(str1, spos, epos - spos)
END,
',' || str2 || ','
FROM bounds
ORDER BY spos
)
SELECT regexp_replace(
xmlcast(Xmlagg(XMLELEMENT(item,item,',')) as clob),
'\s*,\s*$'
) AS str3
FROM items
WHERE str2 NOT LIKE '%,' || item || ',%';
Which outputs:哪个输出:
STR3 STR3 4,8 4,8
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.