【问题标题】:Oracle SQL compare records within a tableOracle SQL 比较表中的记录
【发布时间】:2016-12-08 02:20:47
【问题描述】:

我有一张如下表:

S.No | Item_ID | Item_Revision | Code |
-----+---------+---------------+-------
1.   | item1   | 0             | xyz  |
2.   | item2   | 0             | xyz  |
3.   | item3   | 0             | xyz  |
4.   | item1   | 1             |      |
5.   | item2   | 1             | abc  |
6.   | item3   | 1             | xyz  |

我需要比较表中的记录,找出不同版本的item的代码差异。

我想要的结果集如下:

 | Item_ID | Code_Revision_0 | Code_Revision_1 |
 | item1   | xyz             |                 |
 | item2   | xyz             | abc             |

我无法为此目的制定 oracle 查询。

提前致谢!

【问题讨论】:

    标签: sql oracle inner-join


    【解决方案1】:

    一个基本的想法是使用join:

    select t0.item_id, t0.code as code_0, t1.code as code_1
    from t t0 join
         t t1
         on t0.item_id = t1.item_id and
            t0.item_revision = 0 and
            t1.item_revision = 1
    where t0.code <> t1.code;
    

    但是,如果code 的值为NULL(或空字符串),则需要更加小心:

    where t0.code <> t1.code or (t0.code is null and t1.code is not null) or
          (t0.code is not null and t1.code is null) 
    

    【讨论】:

    • 我将其标记为答案,即使我使用的是 vkp 的查询。因为你的解释让我理解了vkp的查询..谢谢!
    【解决方案2】:

    您可以使用自联接来执行此操作。

    select t1.item_id, t1.code code_rev_0, t2.code code_rev_1
    from tablename t1
    join tablename t2 on t1.item_id=t2.item_id 
    and t1.item_revision = 0 and t2.item_revision = 1
    where nvl(t1.code,'a') <> nvl(t2.code,'a')
    

    【讨论】:

    • 最好避免 where 子句中的 NVL 技巧。除了显而易见('a' 可能是 code 列中的合法值)之外,这个技巧隐藏了意图 - 如果将来另一个数据库专业人员必须维护或修改代码,他们会更容易理解如果像 Gordon 所做的那样完整地写出代码(可能需要修改它)。 (我在我的解决方案中也做了同样的事情,但 Gordon 在我面前展示了正确的方法。)干杯!
    【解决方案3】:

    这是一个使用 PIVOT 运算符而不是自联接的解决方案。如果我正确阅读了执行计划,那么对于您提供的输入数据,这会稍微更有效(连接解决方​​案的成本为 13 与 17)。您可能想根据实际数据测试这两种解决方案,看看哪个效果更好。

    with
         input_data ( item_id, item_revision, code ) as (
           select 'item1', 0, 'xyz' from dual union all
           select 'item2', 0, 'xyz' from dual union all
           select 'item3', 0, 'xyz' from dual union all
           select 'item1', 1, ''    from dual union all
           select 'item2', 1, 'abc' from dual union all
           select 'item3', 1, 'xyz' from dual
         )
    select *
    from input_data
    pivot (max(code) for item_revision in (0 as code_revision_0, 1 as code_revision_1))
    where code_revision_0              != code_revision_1 
       or code_revision_0 is     null and code_revision_1 is not null
       or code_revision_0 is not null and code_revision_1 is     null
    ;
    

    输出:

    ITEM_ CODE_REVISION_0  CODE_REVISION_1
    ----- ---------------- ----------------
    item1 xyz
    item2 xyz              abc
    
    2 rows selected.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-20
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多