在Oracle DB中的两行之间逐列比较

时间:2016-04-12 17:56:25

标签: sql oracle11g

我需要编写一个查询来逐列比较(即:查找差异)数据库中的两行之间。例如:

row1: 10 40 sometext 24
row2: 10 25 sometext 24

执行查询后,它应该只显示有差异的字段(即:第二个字段)

这是我到目前为止所做的事情:

select table1.column1, table1.column2, table1.column3, table1.column4 
from table1 
where somefield in (field1, field2);

上面的查询会向我显示两行上面的一行,如下所示: 10 40某种文字24 10 25 sometext 24

然后我必须手动进行比较,这需要花费很多时间b / c该行包含很多列。

所以我的问题再一次是:如何编写一个只向我显示有差异的列的查询?

由于

2 个答案:

答案 0 :(得分:0)

使用UNPIVOT子句(请参阅http://www.oracle-developer.net/display.php?id=506)将列转换为行,然后过滤掉相同的行(使用GROUP BY HAVING COUNT,最后使用PIVOT获取不同的行仅限列。

答案 1 :(得分:0)

要轻松完成此操作,您需要查询表的元数据以获取每一行。您可以将以下代码用作脚本。

define table_name替换为您的表名和define yes_drop_it = NO。将原始WHERE语法放入where_clause。比较逻辑总是比较为where子句返回的前两行。

whenever sqlerror exit failure rollback;

set linesize 150

define test_tab_name = tst_cf_cols
define yes_drop_it = YES
define order_by = 1, 2
define where_clause = 1 = 1
define tab_owner = user

<<clearfirst>> begin
  for clearout in (
    select 'drop table ' || table_name as cmd
    from all_tables 
    where owner = &&tab_owner and table_name = upper('&&test_tab_name')
    and '&&yes_drop_it' = 'YES'
  ) loop
    execute immediate clearout.cmd;
    execute immediate '
        create table &&test_tab_name as
        select 10 as column1, 40 as column2, ''sometext'' as column3, 24 as column4 from dual
        union all
        select 10 as column1, 25 as column2, ''sometext'' as column3, 24 as column4 from dual
    ';
  end loop;
end;
/

column cfsynt format a4000 word_wrap new_value comparison_syntax

with parms as (select 'parmquery' as cte_name, 'row_a' as corr_name_1, 'row_b' as corr_name_2 from dual)
select 
  'select * from (select ' || LISTAGG(cfcol || ' AS cf_' || trim (to_char (column_id, '000')) || '_' || column_name 
, chr(13) || ', ') WITHIN GROUP (order by column_id) 
  || chr(13) || ' from (select * from parmquery where row_number = 1) ' || corr_name_1 
  || chr(13) || ',  (select * from parmquery where row_number = 2) ' || corr_name_2
  || chr(13) || ') where ''DIFFERENT'' IN (' || LISTAGG ('cf_' || trim (to_char (column_id, '000')) || '_' || column_name, chr(13) || ', ') within group (order by column_id) || ')' 
  as cfsynt
from parms, (
  select 
    'decode (' || corr_name_1 || '.' || column_name || ', ' || corr_name_2
    || '.' || column_name || ', ''SAME'', ''DIFFERENT'')'  
    as cfcol,
    column_name,
    column_id
  from 
    parms, 
    all_tab_columns
  where
    owner = &&tab_owner and table_name = upper ('&&test_tab_name')
);

with parmquery as (select rownum as row_number, vals.* from (
  select * from &&test_tab_name 
  where &&where_clause
  order by &&order_by
  ) vals 
) &&comparison_syntax
;