多个一对多连接到相同的表性能

时间:2017-03-09 10:17:57

标签: sql oracle join database-performance

假设我有ClientProfileAddressPhone ......通过{{1}等多个表引用的表Account所有这些表中的列。

因此,一个客户端可能有多个配置文件,多个地址等等。

我需要通过单一查询获取所有client_id的信息。

如果我写像

这样的查询
Client

和帐户有10个配置文件,10个地址,10个电话和10个帐户我最终在我的结果集中有10000(10x10x10x10)行,但我只需要40(10 + 10 + 10 + 10)。 / p>

我应该更好地编写多个查询,还是有简单的方法让数据库产生更少的行?

更新:添加样本数据:

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

Client

ID | Name | ... ------ | -----------|----- 1 | "John Doe" |

Profile

'地址'

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"   |
...

我不知道ResultSet中的哪个响应是期望的。通常它只是加入,一切都很好 - 这是我第一次开始考虑性能。

2 个答案:

答案 0 :(得分:1)

据我所知,主要问题是重复结果集中的数据。因为您不需要复制任何地址的任何电话号码。我认为决定可能是按行排名并按等级加入

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

答案 1 :(得分:1)

+---------+             +---------+
|         |             |         |
| Client  |------------<| Profile |
|         |             +---------+
|         |
|         |             +---------+
|         |             |         |
|         |------------<| Address |
|         |             +---------+
|         |
|         |             +---------+
|         |             |         |
|         |------------<| Account |
|         |             +---------+
+---------+

对于您所描述的内容,我认为您的数据模型如上所示;如果我错了,请纠正我。

假设以上是正确的,那么你在这里拥有的是一个&#34;深陷陷阱&#34;。基本上,地址和帐户之间的关系(例如)是不明确的。我们知道客户的地址;我们知道客户有很多帐户;但我们不知道哪个地址属于哪个帐户。对于您的应用程序,这可能甚至没有意义。事实上,重新阅读您的问题,解决方案可能就像三个单独的查询一样简单。

select c.*, p.*
from client c
join profile p
on c.id = client_id
;

select c.*, a.*
from client c
join address a
on c.id = client_id
;

select c.*, ac.*
from client c
join account ac
on c.id = client_id
;

        ID NAME               ID  CLIENT_ID PROFILE_TY
---------- ---------- ---------- ---------- ----------
         1 John Doe            1          1 Primary
         1 John Doe            2          1 Secondary
         1 John Doe            3          1 Work
         1 John Doe            4          1 Office
         1 John Doe            5          1 Vacation


        ID NAME               ID  CLIENT_ID ADDRESS
---------- ---------- ---------- ---------- ----------
         1 John Doe            1          1 Paris
         1 John Doe            2          1 London
         1 John Doe            3          1 Tokyo
         1 John Doe            4          1 Moscow
         1 John Doe            5          1 New York


        ID NAME               ID  CLIENT_ID ACCOUNT_NU
---------- ---------- ---------- ---------- ----------
         1 John Doe            1          1 0012301230
         1 John Doe            2          1 0172456123
         1 John Doe            3          1 1234001234
         1 John Doe            4          1 6789134834
         1 John Doe            5          1 2378166341