简体   繁体   English

PL / SQL —连接具有不相关行的子表

[英]PL/SQL — Join Child Tables With Unrelated Rows

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. 我试图在PL / SQL中执行联接,以获取包含多个子表的父记录列表,作为单个查询的一部分。 I'm not an Oracle expert. 我不是Oracle专家。 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. 但是我需要的是JOB和CREDENTIAL列仅列出每个元素一次并且彼此不相关-但仍将James的子记录仅在PERSON是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. (其想法是C#代码将获取查询结果并将其转换为一个父PERSON对象,其中包含对两个子JOB对象和三个子CREDENTIAL对象的引用列表。

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. 我愿意处理冗长的SQL以实现这一点,但是它必须是一个查询,而不是多个查询,并且在C#端组合了结果。

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. 该查询正在做更多的工作,因为它为所有人分配了seqnum。 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. 如果您确实一次只选择一个人,则可以将WHERE子句放在子查询中以使其更有效率。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM