I'm trying to perform a join in PL/SQL to get a list of parent records with multiple child tables back as part of a single query. I'm not an Oracle expert. If I wrote a query like this:
SELECT PEOPLE.PersonName, JOBS.JobName, CREDENTIALS.CredentialName
FROM PEOPLE
LEFT OUTER JOIN JOBS
ON PEOPLE.PersonName = JOBS.PersonName
LEFT OUTER JOIN CREDENTIALS
ON PEOPLE.PersonName = CREDENTIALS.PersonName
WHERE PEOPLE.PersonName = 'James'
I would get a table back that lists every combination of job and credential like so:
RN PERSON JOB CREDENTIAL
1 James Developer MBA
2 James Developer PhD
3 James Developer MCAD
4 James QA MBA
5 James QA PhD
6 James QA MCAD
That's fine, and exactly how you expect a left outer join to work. But what I need is for the JOB and CREDENTIAL columns to only list each element once and be unrelated to each other -- but still list James' child records on, and only on, rows where PERSON is James.
RN PERSON JOB CREDENTIAL
1 James Developer MBA
2 James QA PhD
3 James (null) MCAD
But I'm not sure how to write this join. (The idea is that C# code will take the query results and convert it into one parent PERSON object with lists of references to two child JOB objects and three child CREDENTIAL objects.
Outside this example, though, there's actually a lot more than two child tables, so I can't filter a result-set which is the product of all the child-combinations; I need the columns to be unrelated lists.
I'm willing to deal with hairy SQL to achieve this, but it needs to be one query and not multiple queries with the results combined on the C# side.
Thanks to anyone who can help!
You need to enumerate each list and then use that for joining:
select p.PersonName, j.JobName, c.CredentialName
from Person p left outer join
(select j.*,
row_number() over (partition by PersonName order by jobname) as seqnum
from jobs
) j
on p.PersonName = j.PersonName full outer join
(select c.*,
row_number() over (partition by PersonName order by CredentialName) as seqnum
from Credentials
) c
on p.PersonName = c.PersonName and
j.seqnum = c.seqnum
WHERE p.PersonName = 'James'
This query is doing more work, because it assigns seqnum for all persons. You can put the WHERE clause in the subqueries to make it more efficient, if you are really only selecting one person at a time.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.