假设我有Client
,Profile
,Address
,Phone
......通过{{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中的哪个响应是期望的。通常它只是加入,一切都很好 - 这是我第一次开始考虑性能。
答案 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