簡體   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