我在oracle中遇到以下问题并寻找解决方案。 我想比较两个表的内容,但内容格式彼此不同。
Table CANON
CAN
18102-75|18103-0|18104-88
Table DRUM
DR
18103-0
我必须比较这两个表,并得到结果18102-75和18104-88 目前我有一个Case stament简单地使用等于,它给出了奇怪的结果。
CASE WHEN (CANON .CAN = DRUM .DR)
THEN NULL -- not showing if they are the same
ELSE CANON .CAN
END
答案 0 :(得分:0)
有些东西我不明白......;)
如果您在同一记录中有更多值,请使用“|”分隔字符,你可以定义 - 例如 - 一个PL / SQL函数,它在表中转换你的字符串,然后在你的查询中使用它:
CREATE OR REPLACE TYPE T_CHARACTERS_NESTED_TABLE AS TABLE OF VARCHAR2(10);
/
CREATE OR REPLACE FUNCTION STRING_TO_NESTED_TABLE
(pStringOfCharacters IN VARCHAR2)
RETURN T_CHARACTERS_NESTED_TABLE
PIPELINED
AS
myStringOfCharacters VARCHAR2(32767) DEFAULT pStringOfCharacters || '|';
myPos NUMBER;
BEGIN
LOOP
myPos := INSTR(myStringOfCharacters, '|');
EXIT WHEN NVL(myPos, 0) = 0;
PIPE ROW(TRIM(SUBSTR(myStringOfCharacters, 1, myPos - 1)));
myStringOfCharacters := SUBSTR(myStringOfCharacters, myPos + 1);
END LOOP;
RETURN;
END STRING_TO_NESTED_TABLE;
/
然后:
SELECT CAN
FROM (SELECT T.COLUMN_VALUE AS CAN
FROM CANON C,
TABLE(STRING_TO_NESTED_TABLE(C.CAN)) T)
WHERE CAN NOT IN (SELECT DR
FROM DRUM
WHERE DR IS NOT NULL);
子查询中的条件“WHERE DR not NULL”会阻止您获取空结果集,以防DR列中包含NULL。
答案 1 :(得分:0)
这应该可以解决问题。
select *
from (select substr(can, 1, instr(can, '|', 1, 1) - 1) as can,
case
when level = 1 then
replace(substr(can, 1, instr(can, '|', 1, 1)), '|', '')
else
replace(substr(can,
instr(can, '|', 1, level),
length(can) - instr(can, '|', 1, level)),
'|',
'')
end as drum
from canon
connect by level <= (length(can) - length(replace(can, '|')))
and prior sys_guid() is not null
and prior can = can) x
where not exists (select 'x' from drum y where y.dr = x.drum)
order by 1, 2
SQL小提琴演示:http://sqlfiddle.com/#!4/59a7b/1/0
注意:为了测试目的,我在你的每个表上添加了第二行,因为我想确保它能够工作2行以上,因为逻辑对此很敏感。
作为你问题的第二个答案,如果你想要同一行上的数据(虽然我认为我的第一个查询更有意义),这将为你提供你要求的确切结果(将值全部放在同一行上) CAN的每个值的行:
select can||'|'||listagg(drum,'|') within group (order by drum) as listed
from (select substr(can, 1, instr(can, '|', 1, 1) - 1) as can,
case
when level = 1 then
replace(substr(can, 1, instr(can, '|', 1, 1)), '|', '')
else
replace(substr(can,
instr(can, '|', 1, level),
length(can) - instr(can, '|', 1, level)),
'|',
'')
end as drum
from canon
connect by level <= (length(can) - length(replace(can, '|')))
and prior sys_guid() is not null
and prior can = can) x
where not exists (select 'x' from drum y where y.dr = x.drum)
group by can
order by 1