여러

2017-03-09 1 views
1

내가 Profile처럼 여러 테이블에 의해 참조되는 것 테이블 Client이 가정, Address, Phone, Account ...이 모든 테이블의 client_id 칼럼을 통해.여러

그래서 하나의 클라이언트는 여러 개의 프로필, 여러 개의 주소 등을 가질 수 있습니다.

나는 Client의 모든 정보를 단일 쿼리를 통해 얻어야합니다.

내가 작성하는 경우 내가 필요한거야하지만 내가 내 결과 집합에서 10000 (10x10x10x10) 행으로 끝날 것 10 명 프로필, 10 개 주소, 10 전화 10 개 계정이

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 

및 계정과 같은 쿼리 단지 40 (10 + 10 + 10 + 10).

여러 개의 쿼리를 작성하는 것이 좋으며, 데이터베이스의 행을 줄이는 간단한 방법이 있습니까?

UPD : 추가 샘플 데이터 :

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

'계정'

ID  | CLIENT_ID | ACCOUNT_NUM | ... 
------ | --------- | ------------ | --- 
1  | 1   | "0" | 
2  | 1   | "0172456123" | 
3  | 1   | "12340" | 
4  | 1   | "6789134834" | 
5  | 1   | "2378166341" | 
... 

예상되는 ResultSet의 응답을 알 수 없습니다. 보통 그냥 조인이었고 모든 것이 정상이었습니다. 처음으로 퍼포먼스에 대해 생각하기 시작했습니다.

+1

성능 또는 데이터 표현에 대한 질문입니까? 현재 쿼리는 client_id 열의 인덱스가있는 한 잘 수행됩니다. – jarlh

+0

좀 더 자세한 답변을 얻으려면 몇 가지 샘플 데이터와 예상 결과를 입력하십시오. 성능 문제는 – JohnHC

+0

@jarlh입니다. 모든 열에 대한 색인이 생성됩니다. 조인 때문에 99 %의 데이터 만 복제되므로 결과적으로 10K 개의 행이 두려워요. –

답변

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 
+0

어딘가에서이 해킹을 본 적이 있습니다 - 매우 해킹 된 것 같습니다 :-( –

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

하여 참여할 수 결정은, 당신의 데이터 모델이 위라고 생각합니다 생각; 내가 틀렸다면 나를 바로 잡아주세요.

위의 내용이 정확하다고 가정 할 때 여기에있는 것은 "틈의 함정"입니다. 본질적으로 주소와 계정 간의 관계 (예 :)가 모호합니다. 우리는 고객의 주소를 알고 있습니다. 우리는 고객이 많은 계정을 가지고 있음을 압니다. 어떤 주소가 어떤 계정에 속해 있는지 알 수 없습니다. 귀하의 응용 프로그램에, 그것은 심지어 말이되지 않을 수도 있습니다. 사실, 질문을 다시 읽으면 솔루션은 3 가지 별도의 쿼리만큼 간단해질 수 있습니다.

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 0
     1 John Doe   2   1 0172456123 
     1 John Doe   3   1 12340
     1 John Doe   4   1 6789134834 
     1 John Doe   5   1 2378166341 
+0

하지만 데이터베이스에 3 개의 루트가 있습니다.이 문제를 해결하는 "표준"방법이 있는지 궁금합니다. –

+0

@DmitryZvorygin. 내가 제기 한 질문에 정말로 답변하지 않았습니다. (예 :) 계좌와 주소 사이의 관계가 있습니까? 예에서 보여준 결과는 정확합니까? 왕복을 걱정하기 전에 알아 보도록하겠습니다. – BobC

+0

예, 결과가 정확합니다 - 프로필, 계정 및 주소는 정확합니다. –