假设我有一个表Client
,它被多个表引用,例如Profile
、Address
、Phone
、Account
...通过所有这些表中的 client_id
列。
因此,一个客户可能有多个个人资料、多个地址等等。
我需要通过单个查询获取所有Client
的信息。
如果我写这样的查询
SELECT C.*, PR.*, AD.*, PH.*, AC.* FROM CLIENT C
LEFT OUTER JOIN PROFILE PF ON C.ID=PF.CLIENT_ID
LEFT OUTER JOIN ADDRESS AD ON C.ID=AD.CLIENT_ID
LEFT OUTER JOIN PHONE PH ON C.ID=PH.CLIENT_ID
LEFT OUTER JOIN ACCOUNT AC ON C.ID=AC.CLIENT_ID
并且帐户有 10 个个人资料、10 个地址、10 个电话和 10 个帐户,结果集中我最终会得到 10000 (10x10x10x10) 行,尽管我只需要 40 (10+10+10+10)。
我应该更好地编写多个查询还是有简单的方法可以使数据库产生更少的行?
更新:添加示例数据:
客户端
ID | Name | ...
------ | -----------|-----
1 | "John Doe" |
简介
ID | CLIENT_ID | TYPE | ...
------ | --------- | ----------- | ---
1 | 1 | "Primary" |
2 | 1 | "Secondary" |
3 | 1 | "Work" |
4 | 1 | "Office" |
5 | 1 | "Vacation" |
...
“地址”
ID | CLIENT_ID | ADDRESS_TEXT | ...
------ | --------- | ------------ | ---
1 | 1 | "Paris, ..." |
2 | 1 | "London..." |
3 | 1 | "Tokyo..." |
4 | 1 | "Moscow" |
5 | 1 | "New York" |
...
“帐户”
ID | CLIENT_ID | ACCOUNT_NUM | ...
------ | --------- | ------------ | ---
1 | 1 | "0012301230" |
2 | 1 | "0172456123" |
3 | 1 | "1234001234" |
4 | 1 | "6789134834" |
5 | 1 | "2378166341" |
...
我不知道 ResultSet 中会出现哪个响应。通常这只是连接,一切都很好 - 这是我第一次开始考虑性能。
最佳答案
据我了解,主要问题是结果集中的数据重复。因为您不需要为任何地址重复任何电话号码。我认为这个决定可能是对每一行进行排名并按排名加入
with CLIENT(ID) as (
select 1 from dual)
,PROFILE (CLIENT_ID, PROFILE) as (
select 1, 'p1' from dual union all
select 1, 'p2' from dual union all
select 1, 'p4' from dual
)
,ADDRESS (CLIENT_ID, ADDRESS) as (
select 1, 'H1' from dual union all
select 1, 'H2' from dual
)
,PHONE (CLIENT_ID, PHONE) as (
select 1, '+13123411' from dual union all
select 1, '+1234512344' from dual union all
select 1, '+12345123133' from dual union all
select 1, '+12345123123' from dual union all
select 1, '+1234512144' from dual union all
select 1, '+12345123123' from dual union all
select 1, '+1234512144' from dual union all
select 1, '+12345123123' from dual union all
select 1, '+1234512144' from dual union all
select 1, '+12345123123' from dual union all
select 1, '+1234512144' from dual
)
,ACCOUNT (CLIENT_ID, ACCOUNT) as (
select 1, 'Acc1' from dual union all
select 1, 'acc2' from dual
)
SELECT PROFILE ,ADDRESS ,PHONE ,ACCOUNT
from
(select rownum as RN, PROFILE from PROFILE PR where PR.CLIENT_ID IN (select id from CLIENT c where c.id = 1)) a
full outer join (select rownum as RN, ADDRESS from ADDRESS PR where PR.CLIENT_ID IN (select id from CLIENT c where c.id = 1)) b on a.rn = b.rn
full outer join (select rownum as RN, PHONE from PHONE PR where PR.CLIENT_ID IN (select id from CLIENT c where c.id = 1)) c on a.rn = c.rn
full outer join (select rownum as RN, ACCOUNT from ACCOUNT PR where PR.CLIENT_ID IN (select id from CLIENT c where c.id = 1)) d on a.rn = d.rn
关于sql - 多个一对多连接同一张表的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42692605/