Oracle比较具有管道符号的表内容

时间:2014-02-13 13:13:23

标签: sql oracle

我在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

2 个答案:

答案 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