【问题标题】:Oracle connect by level complicationOracle 按级别连接复杂度
【发布时间】:2015-08-01 16:39:05
【问题描述】:

我在查询将一行分成两部分时遇到了困难。

我的样本数据:

       ID OLD                      NEW                    
---------- ------------------------ ------------------------
        12 L-D / T-E                L-E / T-E               
        13 L-D / T-E                L-D / T-D               
        14 L-D / T-E                L-E / T-D 

新旧值不同的地方,我想将它们分开,所以我的输出应该是:

id | OLD | NEW
12 | L-D | L-E  //in this instance T hasn't changed so I will ignore it.
13 | T-E | T-D  //similar to the above but this time only add T
14 | L-D | L-E  //both values have changed, two rows required
14 | T-E | T-D

我已经整理了一个“工作”示例,但结果是重复的。我认为问题在于按级别连接,我对 Oracle 还很陌生,所以调试有点困难。

非常感谢任何帮助。

这是我用来删除、创建和运行查询的查询:

它在 sqldeveloper 中运行良好,但不确定 sqlplus 是否会对它印象深刻。

    drop table t;
CREATE TABLE T
    (id int, 
     old varchar2(24), 
     new varchar2(24))
;

INSERT ALL

      INTO T (id, old, new)
         VALUES (12, 'L-D / T-E', 'L-E / T-E')
      INTO T (id, old, new)
         VALUES (13, 'L-D / T-E', 'L-D / T-D')
      INTO T (id, old, new)
         VALUES (14, 'L-D / T-E', 'L-E / T-D')

SELECT * FROM dual
;


SELECT * FROM T;

--insert into t (id, old, new) values (1,'dasdsad', 'asdasd');

BEGIN
INSERT INTO t (id,old, new) 

  WITH DATA AS
      (SELECT id,OLD, new
      FROM t
      WHERE 
      --multiple changes
      (
        (SUBSTR(OLD,3,1) <> SUBSTR(NEW, 3,1)
        AND SUBSTR(OLD, 9)    <> SUBSTR(NEW, 9)
        )
      OR
        --row 2 old/new L are same, old/new T are not
        (SUBSTR(OLD,3,1) = SUBSTR(NEW, 3,1)
        AND SUBSTR(OLD, 9)    <> SUBSTR(NEW, 9)
        )

      OR
        --row 1
        (SUBSTR(OLD,3,1) <> SUBSTR(NEW, 3,1)
        AND SUBSTR(OLD, 9) = SUBSTR(NEW, 9)
        )

      )
      )

    SELECT id, trim(regexp_substr(OLD, '[^/]+', 1, LEVEL)) OLD,  
               trim(regexp_substr(NEW, '[^/]+', 1, LEVEL)) NEW
    FROM DATA
      CONNECT BY (LEVEL <= regexp_count(new, '/')+1);

END;
 /

【问题讨论】:

    标签: sql oracle stored-procedures plsql


    【解决方案1】:

    我个人不会使用递归语法。

    首先,我将创建虚拟列(或视图)以从查询中消除繁琐的 substring 函数,以这种方式:

    ALTER TABLE t ADD ( OLD_LEFT AS ( Substr( OLD, 1, 3 )));
    ALTER TABLE t ADD ( OLD_RIGHT AS ( Substr( OLD, 7, 3 )));
    ALTER TABLE t ADD ( NEW_LEFT AS ( Substr( NEW, 1, 3 )));
    ALTER TABLE t ADD ( NEW_RIGHT AS ( Substr( NEW, 7, 3 )));
    

    或:

    CREATE VIEW tt AS
    SELECT ID, OLD, NEW,
           Substr( OLD, 1, 3 ) As OLD_LEFT,
           Substr( OLD, 7, 3 ) As OLD_RIGHT,
           Substr( NEW, 1, 3 ) As NEW_LEFT,
           Substr( NEW, 7, 3 ) As NEW_RIGHT
    FROM t;
    

    经过上面的简化,查询就很直接了,只是:

    SELECT id, OLD_LEFT , NEW_LEFT 
    FROM T
    WHERE OLD_LEFT <> NEW_LEFT
    UNION ALL
    SELECT id, OLD_RIGHT , NEW_RIGHT 
    FROM T
    WHERE OLD_RIGHT <> NEW_RIGHT
    ORDER BY ID
    

    演示:http://sqlfiddle.com/#!4/2fdc4/2

    【讨论】:

    • 无语。昨天我花了几个小时研究一个解决方案,它可以工作并且做它应该做的,但是为了能够简化它,这就是......该死的。 :)
    • 我的实际实现也更丑陋。 codereview.stackexchange.com/questions/98774/…
    猜你喜欢
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 2017-10-17
    • 2017-12-29
    • 2019-05-12
    相关资源
    最近更新 更多