2017-02-20 111 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