2017-02-20 106 views
0

我在編寫一個看起來應該很簡單的查詢時遇到了一些麻煩,但解決方案正在逃避我。Oracle查詢3個帶有2個外部連接的表格

我們有三個表(簡化這個問題的目的): 者 - 用戶名的表:

per_id  number(10) - primary key, populated by a sequence 
    user_name varchar2(50) 
    user_id  varchar2(15) - unique, basically the employee ID 

work_assignments - 有點像船員外派,但更普遍的:

wa_id  number(10) - primary key, populated by a sequence 
    wa_name varchar2(25) 

current_assignments - 哪些用戶擁有哪些work_assignments;每用戶平均大約爲25的工作任務,但有些「幸運」的人有向上的150:

wa_id number(10) 
    per_id number(10) 

我想寫一個查詢,將比較work_assignments兩個用戶中,一共有三個列。結果應該是這樣的:

WA_Name User_Name1 User_Name2 
Crew A Bob   Joe 
Crew B     Joe 
Crew C Bob 

基本上每個要麼兩個用戶都有,與誰擁有它的用戶(一個或多個)的姓名(或名稱)work_assignment。

這是我能想出最接近的(當然,我也拿出來與3子查詢,沒有工作一個醜陋的查詢,但是看起來應該有一個更優雅的解決方案):

select distinct * from (
    select wa.name  work_assignment, 
     per.name  user_name1, 
     per2.name user_name2 
    from work_assignments wa join current_assignments ca on wa.wa_id = ca.wa_id 
           join current_assignments ca2 on wa.wa_id = ca2.wa_id 
        left outer join persons per on per.per_id = ca.per_id and per.user_id = 'X12345' 
        left outer join persons per2 on per2.per_id = ca2.per_id and per2.user_id = 'Y67890' 
        ) 
    where user_name1 is not null or user_name2 is not null 
    order by 1; 

這一個問題是,如果兩個用戶有一個工作任務,它顯示了3個記錄:一個是鮑勃,一個是喬,一個兩個:

WA_Name User_Name1 User_Name2 
Crew A Bob   Joe 
Crew A     Joe 
Crew A Bob 

請幫幫忙!

感謝, 丹

+0

雖然我已經接受BobC的回答,但我仍然有興趣瞭解是否有人有不同的方法。謝謝! – AndyDan

回答

1

我創建了一個樣本數據集/表

drop table persons; 
drop table work_assgn; 
drop table curr_assgn; 


create table persons(
    per_id number(10) not null 
, user_name varchar2(10) not null 
, user_id varchar2(10) not null 
) 
; 

insert into persons values(1, 'Bob', 'X123'); 
insert into persons values(2, 'Joe', 'Y456'); 
insert into persons values(3, 'Mike', 'Z789'); 
insert into persons values(4, 'Jeff', 'J987'); 

commit; 

create table work_assgn(
    wa_id number(10) not null 
, wa_name varchar2(25) 
) 
; 

insert into work_assgn values(10, 'Crew A'); 
insert into work_assgn values(20, 'Crew B'); 
insert into work_assgn values(30, 'Crew C'); 
insert into work_assgn values(40, 'Crew D'); 

commit; 

create table curr_assgn(
    wa_id number(10) not null 
, per_id number(10) not null 
) 
; 

insert into curr_assgn values(10, 1); 
insert into curr_assgn values(10, 2); 
insert into curr_assgn values(20, 2); 
insert into curr_assgn values(30, 1); 
insert into curr_assgn values(40, 4); 

commit; 


select * from persons; 
select * from work_assgn; 
select * from curr_assgn; 

所以數據的模樣

PERSONS 
    PER_ID USER_NAME USER_ID 
---------- ---------- ---------- 
     1 Bob  X123 
     2 Joe  Y456 
     3 Mike  Z789 
     4 Jeff  J987 


WORK_ASSGN 
    WA_ID WA_NAME 
---------- ------------------------- 
     10 Crew A 
     20 Crew B 
     30 Crew C 
     40 Crew D 

CURRASSGN 
    WA_ID  PER_ID 
---------- ---------- 
     10   1 
     10   2 
     20   2 
     30   1 
     40   4 

一種方法可以是使用PIVOT

with assignment as 
(
select p.user_id, p.user_name, a.wa_name 
from persons p 
join curr_assgn c 
    on p.per_id =c.per_id 
join work_assgn a 
    on a.wa_id = c.wa_id 
where p.user_id in ('X123', 'Y456') 
) 
select * from assignment 
pivot 
(max(user_name) for user_id in ('X123', 'Y456') 
) 
; 
+0

不幸的是,在一個和我們一樣大的組織中,user_name不是唯一的。我可以識別超過1400個人名錶中有多個條目的名稱。這就是爲什麼我必須加入user_id。我嘗試使用user_id而不是user_name,但它給了我所有的work_assignments,即使Joe和Bob都沒有分配給它。有沒有辦法過濾掉那些沒有用戶的記錄?我不熟悉PIVOT。 – AndyDan

+0

@AndyDan,這意味着您可以有1400列寬的報告? – BobC

+0

不,我一次也不會比較超過2人的工作任務。該報告應該只有3列:工作任務名稱,用戶名1,用戶名2.這只是我們可能有3或4個「喬」,所以我不能過濾用戶名。但我寧願在報告中使用用戶名稱而不是用戶名稱。 – AndyDan