繁体   English   中英

用于比较oracle中同一表中多列的SQL查询

[英]SQL query to compare multiple columns in same table in oracle

我需要在同一个表中找到具有数据差异的 emplid。 表由 50-60 列组成。

我创建了一个基本查询并且它正在工作,但需要某种方法来实现相同的目的,因为我不想写每个列名。

我的查询:

select 
    emplid 
from 
    ps_custom_tbl t, ps_custom_tbl prev_t 
where 
    prev_t.emplid = t.emplid 
    and t.effdt = (select max effdt from ps_custom_tbl t2 
                   where t2.emplid = t.emplid) 
    and prev_t.effdt = (select max(effdt) from ps_custom_tbl prev_t2 
                        where emplid = prev_t.emplid and effdt < t.effdt)
    and (t.first_name prev_t.first_name Or t.last_name prev_t.last_name …. 50 columns);

你能建议另一种方法来实现同样的事情吗?

无论您做什么,您都必须在某种意义上编写所有列。

在比较当前和以前,您可能会发现这更容易

select 
  col1,
  col2,
  ...
  lag(col1) over ( partition by empid order by effdt ) as prev_col1,
  lag(col2) over ( partition by empid order by effdt ) as prev_col2
  ...

然后你的比较将沿着

select *
from (  <query above >
where
  decode(col1,prev_col1,0,1) = 1 or 
  decode(col2,prev_col2,0,1) = 1 or 
  ...

以这种方式使用 DECODE 可以处理空值问题。

您可以使用减号。

如果 no_data 那么两者都是相同的,如果有一些记录 - 意味着两者之间存在差异

create table emp as select * from hr.employees;

insert into emp select employee_id+1000, first_name, last_name, email, phone_number, hire_date, job_id, salary, commission_pct, manager_id, 
 decode(department_id ,30,70, department_id)
 from hr.employees;

select first_name, last_name, email, phone_number, hire_date, job_id, salary, commission_pct, manager_id, department_id  
from emp where employee_id <= 1000
minus
select first_name, last_name, email, phone_number, hire_date, job_id, salary, commission_pct, manager_id, department_id  
from emp where employee_id > 1000;

但是您必须列出所有列,因为如果您有不同的日期或 ID,它们也会被比较。 但是在 SELECT 子句中列出列然后为每个人编写 WHERE 条件更容易。 也许它会有所帮助。

-- 或者如果不同的表并想比较所有列就简单地做

drop table emp;
create table emp as select * from hr.employees;
    
create table emp2  as 
select employee_id, first_name, last_name, email, phone_number, hire_date, job_id, salary, commission_pct, manager_id, 
 decode(department_id ,30,70, department_id) department_id
 from hr.employees;

select * from emp
minus 
select * from emp2;

---- 添加日期标准

-- 是的,您可以添加日期条件并使用分析函数检查哪个 -- 较新,哪些是

年龄较大,然后比较。 像下面这样:

drop table emp;
create table emp as select * from hr.employees;
        
insert into emp 
        select
           employee_id, 
           first_name, 
           last_name, 
           email, 
           phone_number, 
           hire_date+1, 
           job_id, 
           salary, 
           commission_pct, 
           manager_id, 
           decode(department_id ,30,70, department_id)
        from hr.employees;
        
     with data as   --- thanks to WITH you retrieve data only once
            (select employee_id, first_name, last_name, email, phone_number, 
                hire_date, 
                row_number() over(partition by employee_id order by hire_date desc) rn  -- distinguish newer and older record, 
               job_id, salary, commission_pct, manager_id, department_id  
        from emp)
        select employee_id, first_name, last_name, email, phone_number, department_id from data where rn  = 1
        MIUNUS--- find the differences
        select employee_id, first_name, last_name, email, phone_number, department_id from data where rn = 2;

我的要求是将数据发送给经理,他们更改列中的任何/全部/无数据,然后发回给我。 然后,我必须识别与我发送的内容不同的每一列,并将这些列标记为已更改,以便中央办公室审核员直观地扫描和批准/拒绝将更改集成回中央数据集。

当然,此解决方案可能不适合您的需求,但此处提供了模板结构,无论列数如何,您都可以对其进行扩充以满足您的需求。 就您的问题而言,50-60 列将使此 SQL 查询变得庞大,但我过去曾编写过非常长的查询并取得了巨大成功。 根据此模板一次添加几个列,而不是全部添加列,然后查看它们是否在此过程中起作用。

您可以轻松地编写 pl/sql 来为您编写有关表的查询。 如果您必须比较 3 个或更多表中的列或双向更改,这将变得非常麻烦。 我只关心单向变化。 该人是否更改了我的原始行列。 如果是这样,他们改变了哪些列,我的前值是什么,他们的后值是什么,请不要向我展示其他内容。

换句话说,只向我显示列的行与之前的值发生了变化,而没有其他任何内容。

create table thing1 (id number, firstname varchar2(10), lastname varchar2(10));
create table thing2 (id number, firstname varchar2(10), lastname varchar2(10));

insert into thing1 values (1,'Buddy', 'Slacker');
insert into thing2 values (1,'Buddy', 'Slacker');
insert into thing1 values (2,'Mary', 'Slacker');
insert into thing2 values (2,'Mary', 'Slacke');
insert into thing1 values (3,'Timmy', 'Slacker');
insert into thing2 values (3,'Timm', 'Slacker');
insert into thing1 values (4,'Missy', 'Slacker');
insert into thing2 values (4,'Missy', 'Slacker');
commit;

取消注释注释 select * 在每个数据集之后一次查询一个,以了解每个数据集中在细化过程的每个阶段的内容。

with rowdifferences as
(
select
id
,firstname
,lastname
from thing2
minus
select
id
,firstname
,lastname
from thing1
)
--select * from rowdifferences
,thing1matches as
(
select
t1.id
,t1.firstname
,t1.lastname
from thing1 t1
join rowdifferences rd on t1.id = rd.id
)
--select * from thing1matches
, col1differences as
(
select
id
,firstname
from rowdifferences
minus
select
id
,firstname
from thing1matches
)
--select * from col1differences
, col2differences as
(
select
id
,lastname
from rowdifferences
minus
select
id
,lastname
from thing1matches
)
--select * from col2differences
,truedifferences as
(
select
case when c1.id is not null then c1.id
when c2.id is not null then c2.id
end id
,c1.firstname
,c2.lastname
from col1differences c1
full join col2differences c2 on c1.id = c2.id
)
--select * from truedifferences
select
t1m.id
,case when td.firstname is not null then t1m.firstname end beforefirstname
,td.firstname afterfirstname
,case when td.lastname is not null then t1m.lastname end beforelastname
,td.lastname afterlastname
from thing1matches t1m
join truedifferences td on t1m.id = td.id
;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM