2017-02-20 2 views
0

У меня возникли проблемы с написанием запроса, который кажется, что он должен быть простым, но решение уклоняется от меня.Oracle Query на 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 - какие пользователи имеют какие рабочие_значения; в среднем на одного пользователя составляет около 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 

Пожалуйста, помогите!

Спасибо, Dan

+0

Хотя я принял ответ Боба, мне все равно было бы интересно узнать, есть ли у кого-то другой подход. Благодаря! – 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

К сожалению, в такой большой нашей организации имя пользователя не уникально. Я могу идентифицировать более 1400 имен, которые содержат более одной записи в таблице лиц. Вот почему я должен присоединиться к user_id. Я попробовал это, используя user_id, а не user_name, но дал мне все рабочие_замены, даже если ни Джо, ни Боб не были назначены ему. Есть ли способ отфильтровать те записи, у которых нет ни одного пользователя? Я не знаком с PIVOT. – AndyDan

+0

@ AndyDan, так что вы можете иметь отчет шириной 1400 столбцов? – BobC

+0

Нет, я бы никогда не сравнивал задания на работу более двух человек за раз. В отчете должно быть всего 3 столбца: имя задания на работу, имя пользователя 1, имя пользователя 2. Просто мы можем иметь 3 или 4 «Joe», поэтому я не могу фильтровать только имя пользователя. Но я предпочел бы иметь имя пользователя в отчете, чем идентификатор пользователя. – AndyDan

Смежные вопросы