Reputation: 3
So, I have a table:
id place user role
____________________________
1 a u1 emp
2 a u2 emp
3 a u3 smallBoss
4 b u4 emp
5 b u5 emp
6 b u6 smallBoss
7 b u7 medBoss
Now, I want to create a view with these users and their bosses in additional column with these rules:
1 - if user do have smallBoss
at his place, smallBoss
is in boss
column no matter what!!!
2 - if user doesn't have smallBoss
at his place, then medBoss
is in boss
column if he is present, but if not then bigBoss
is the boss
3 - obviously, smallBoss at place b
will have medBoss
in his boss
column
4 - bigBoss
is last option
Conclusion: bosses have some kind of reverse priorities:
1 - smallBoss
- if he is present, he is surely boss for emp
2 - medBoss
- if he is present, he is boss for all smallBoss
and if there is no smallBoss
at a place, then he is the boss for all emp
3 - 'bigBoss' - he is present everywhere, but should only be boss for medBoss
and for emp
where neither smallBoss
nor medBoss
is present.
I tried join versions and union. Union seems to be closest to my goal, but I have multiple users with different bosses (users u4
and u5
are doubled!!!). I want u4
and u5
to show just once with smallBoss in their boss
column:
id place user role boss
___________________________________________
1 a u1 emp smallBoss
2 a u2 emp smallBoss
3 a u3 smallBoss bigBoss
4 b u4 emp smallBoss
5 b u5 emp smallBoss
6 b u6 smallBoss medBoss
7 b u7 medBoss bigBoss
Upvotes: 0
Views: 852
Reputation:
You need neither joins nor unions; what you do need are analytic functions and case
expressions. (In this solution, analytic max()
.)
As the query below shows, it would be a lot easier if you used a coding system for "roles" - 0 for employee, 1 for smallBoss, etc. As it is, we need to create it "on the fly" in the query.
USER and ROLE are reserved words in Oracle, they shouldn't be used as column names (not even as replacements for posting here, if they are not your actual column names); I replaced them with USR and RL.
I assumed there are only four possibilities, with the following rules. If my assumption is wrong, you should be able to adapt the query to your actual possibilities and rules; you should be able to see easily how each possibility and rules are reflected in the query.
If there are only emp at a place, they all have medBoss for boss.
If there are only emp and smallBoss, then emp have smallBoss as the boss, and smallBoss has bigBoss.
If there are emp, smallBoss and medBoss, then smallBoss is the boss of emp, medBoss is the boss of smallBoss and bigBoss is the boss of medBoss.
If there are emp, smallBoss, medBoss and bigBoss, then the rules are like in the last paragraph, and bigBoss has no boss (null
) - that is the most common way to represent that in a hierarchical table.
with
test_data ( id, place, usr, rl ) as (
select 1, 'a', 'u1', 'emp' from dual union all
select 2, 'a', 'u2', 'emp' from dual union all
select 3, 'a', 'u3', 'smallBoss' from dual union all
select 4, 'b', 'u4', 'emp' from dual union all
select 5, 'b', 'u5', 'emp' from dual union all
select 6, 'b', 'u6', 'smallBoss' from dual union all
select 7, 'b', 'u7', 'medBoss' from dual
)
-- End of test data (not part of the query). The SQL query begins BELOW THIS LINE.
select id, place, usr, rl,
case max(rl_code) over (partition by place)
when 0 then 'medBoss'
when 1 then case rl_code when 0 then 'smallBoss'
when 1 then 'bigBoss' end
when 2 then case rl_code when 0 then 'smallBoss'
when 1 then 'medBoss'
when 2 then 'bigBoss' end
when 3 then case rl_code when 0 then 'smallBoss'
when 1 then 'medBoss'
when 2 then 'bigBoss' end
end as boss
from (
select id, place, usr, rl,
case rl when 'emp' then 0
when 'smallBoss' then 1
when 'medBoss' then 2
when 'bigBoss' then 3 end as rl_code
from test_data
)
order by place, id -- if needed
;
Output:
ID PLACE USR RL BOSS
-- ----- --- --------- ----------
1 a u1 emp smallBoss
2 a u2 emp smallBoss
3 a u3 smallBoss bigBoss
4 b u4 emp smallBoss
5 b u5 emp smallBoss
6 b u6 smallBoss medBoss
7 b u7 medBoss bigBoss
7 rows selected.
Upvotes: 1