Oracle11g Oracle查询3个具有2个外部联接的表

Oracle11g Oracle查询3个具有2个外部联接的表,oracle11g,outer-join,ansi,Oracle11g,Outer Join,Ansi,我在编写一个看起来应该很简单的查询时遇到了一些困难,但解决方案是回避我 我们有三个表格(为解决此问题而简化): 人员-用户名表: per_id number(10) - primary key, populated by a sequence user_name varchar2(50) user_id varchar2(15) - unique, basically the employee ID 工作分配-有点像团队分配,但更一般: wa_id

我在编写一个看起来应该很简单的查询时遇到了一些困难,但解决方案是回避我

我们有三个表格(为解决此问题而简化): 人员-用户名表:

  per_id      number(10) - primary key, populated by a sequence
  user_name   varchar2(50)
  user_id     varchar2(15) - unique, basically the employee ID
工作分配-有点像团队分配,但更一般:

  wa_id     number(10) - primary key, populated by a sequence
  wa_name   varchar2(25)
当前工作分配-哪些用户有哪些工作分配;每个用户的平均工作分配数约为25份,但一些“幸运”的用户的工作分配数超过150份:

  wa_id   number(10)
  per_id  number(10)
我正在尝试编写一个查询来比较两个用户的工作分配,总共有三列。结果应该如下所示:

WA_Name   User_Name1    User_Name2
Crew A    Bob           Joe
Crew B                  Joe
Crew C    Bob
基本上,两个用户中任何一个拥有的每个工作分配,以及拥有它的用户的名称

下面是我能想到的最接近的方法(好吧,我确实提出了一个丑陋的查询,其中有3个子查询可以完成这项工作,但似乎应该有一个更优雅的解决方案):

这一个的问题是,如果两个用户都有工作分配,它会显示3条记录:一条记录用于Bob,一条记录用于Joe,另一条记录用于两者:

WA_Name   User_Name1    User_Name2
Crew A    Bob           Joe
Crew A                  Joe
Crew A    Bob
请帮忙

谢谢,
Dan

我创建了一组示例数据/表格

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
一种方法可能是使用枢轴

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' )
)
;

不幸的是,在像我们这样大的组织中,用户名不是唯一的。我可以识别1400多个姓名,这些姓名在persons表中有多个条目。这就是为什么我必须使用user\u id加入。我尝试使用user\u id而不是user\u name,但它给了我所有的工作分配,即使Joe和Bob都没有分配给它。有没有办法过滤掉那些既没有用户也没有用户的记录?我对PIVOT不熟悉。@AndyDan这意味着你可以有一份1400栏宽的报告?不,我不会一次比较两个人以上的工作分配。报告应该只有3列:工作分配名称、用户名1、用户名2。只是我们可能会有3或4个“Joe”,所以我不能只根据用户名进行筛选。但我更希望报告中有用户名,而不是用户名。@AndyDan啊,所以你会按用户名进行筛选。我现在在你最初的问题中看到了这一点,但我没有建立连接。在外部联接解决方案中,您是在per_id上联接的;通常,我在语义上不知道需要什么。PIVOT是在11g中引入的,它是一种将行转换为列以创建交叉选项卡样式报告的方法。让我重做我的答案……事实上,我想我在《Oracle®数据库SQL语言参考手册》中找到了一些PIVOT示例后就找到了答案。我马上把我的问题贴在这里,看看你怎么想。虽然我已经接受了BobC的回答,但我仍然有兴趣看看是否有人有不同的方法。谢谢
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' )
)
;