2016-09-02 2 views
0

조인PL/SQL은 I 3 개 테이블이

  • A (T_REF 정수 l_date 일)
  • B (T_REF 정수 client_ref 정수)
  • C (t_id 정수를 client_ref 정수)
    및 매개 변수 (client_ref_ integer).
    1) client_ref 연결 테이블 B의 행이있는 경우 (쿼리

    select b.t_ref from B b where b.client_ref = client_ref_ 
    

    반환하는 모든 데이터), 내 쿼리 보면됩니다 :

나는 조건 테이블 A에서 데이터를 선택해야합니다 이 같은 :

select max(l_date) from A where t_ref in (select b.t_ref from B b where b.client_ref = client_ref_) 

2) 쿼리가 위의 모든 데이터를 반환하는 경우, 내 쿼리가 다음과 같이 표시됩니다

select max(l_date) from A where t_ref in (select c.t_id from C c where c.client_ref = client_ref_) 
지금 내가 PLSQL 함수를 작성했습니다 :

select max(aa.l_date) into l_date from A aa where aa.t_ref in (select bb.t_ref from B bb where bb.client_ref = client_ref_); 
    if l_date is null then 
    select max(aa.l_date) into l_date from A aa where t_ref in (select t_id from C c where c.client_ref = client_ref_); 
    end if; 
return l_date; 

그것은 작동을하지만 테이블에게 2 번 호출하기 때문에, 좋은 생각이 아니다. 두 번째 호출을 피하고 하나의 쿼리에서이 작업을 수행 할 수 있습니까?

+0

첫 번째 선택이 실패합니다. 테이블을 별칭으로 선택 쿼리에서 단일 a를 사용했습니다. max (a.l_date) into l_date – XING

+0

죄송합니다. typinq 실수였습니다. 그러나 그것은 주요한 문제가 아닙니다. – user3533397

답변

0
with 
    prep (t_ref, idx) as (
     select b.t_ref, 1 
     from table_B b 
     where b.client_ref = :client_ref 
     union all 
     select c.t_ref, 2 
     from table_C c 
     where c.client_ref = :client_ref 
    ) 
select max(a.l_date) keep (dense_rank first order by p.idx) -- into l_date 
from table_A a inner join prep p 
       on a.t_ref = p.t_ref 
; 

설명 : 우선 client_ref 일치하는 행의 스캔 table_B; 발견 된 것이 있으면 그것을 모으고 1의 "색인"을 붙이십시오. 그런 다음 table_C을 스캔하고 동일한 작업을 수행하지만 인덱스는 2입니다. (table_C이 매우 큰 경우 에 :client_ref이 발견되면 시간이 낭비되며, 문제가되는 경우 조금 더 많은 코드로 해결할 수 있습니다. 그런 다음 table_A이 두 세트의 행을 결합한 결과와 결합됩니다. keep dense_rank first...idx = 1 인 행만 max(l_date)으로 간주하지만 해당 행이없는 경우 idx = 2 행만 고려합니다.

:client_ref이 표 B 및 C 중 하나에 없으면 결과는 max(l_date)null이됩니다.

쿼리를 테스트 할 수 있도록 :clent_ref을 바인드 변수로 사용하여 쿼리를 작성했습니다. 변수 이름으로 변경할 수 있습니다. client_ref_

1

다음과 같은 방법으로 사용할 수 있습니다. 여기에서 모든 사례를 다뤘습니다. 확인하십시오

create table A (t_ref integer, l_date date); 

create table B (t_ref integer, client_ref integer); 

create table C (t_id integer, client_ref integer); 



SQL> select * from a 
    2/

    T_REF L_DATE 
---------- --------- 
     10 01-JAN-11 
     20 02-FEB-11 
     30 02-MAR-11 

SQL> select * from b; 

    T_REF CLIENT_REF 
---------- ---------- 
     10  101 
     20  102 

SQL> select * from c; 

     T_ID CLIENT_REF 
---------- ---------- 
     10  101 
     20  102 
     30  101 
     40  103 




sql> select max(aa.l_date) 
    --into l_date 
    from A aa 
    where aa.t_ref =any( case when (select bb.t_ref from B bb where bb.client_ref = '101' and rownum <2) is null then 
            (select t_id from C c where c.client_ref = '101') 
            when (select t_id from C c where c.client_ref = '101' and rownum <2) is not null then 
             (select t_id from C c where c.client_ref = '101' and rownum <2 ) 
             else 
            (select bb.t_ref from B bb where bb.client_ref = '101') 
            end 
         ); 

MAX(AA.L_ 
--------- 
01-JAN-11 



SQL> select max(aa.l_date) 
--into l_date 
from A aa 
where aa.t_ref =any( case when (select bb.t_ref from B bb where bb.client_ref = '102' and rownum <2) is null then 
           (select t_id from C c where c.client_ref = '102') 
           when (select t_id from C c where c.client_ref = '102' and rownum <2) is not null then 
             (select t_id from C c where c.client_ref = '102' ) 
            else 
           (select bb.t_ref from B bb where bb.client_ref = '102') 
            end 
        ); 

MAX(AA.L_ 
--------- 
02-FEB-11 


SQL> select max(aa.l_date) 
--into l_date 
from A aa 
where aa.t_ref =any( case when (select bb.t_ref from B bb where bb.client_ref = '103' and rownum <2) is null then 
           (select t_id from C c where c.client_ref = '103') 
           when (select t_id from C c where c.client_ref = '103' and rownum <2) is not null then 
            (select t_id from C c where c.client_ref = '103' ) 
            else 
           (select bb.t_ref from B bb where bb.client_ref = '103') 
            end 
        ); 

MAX(AA.L_ 
--------- 


SQL> 
+0

오류를 반환합니다 : 단일 행 하위 쿼리는 둘 이상의 행을 반환합니다. – user3533397

+0

테이블 a, b, c의 일부 샘플 데이터를 공유 할 수 있습니까 – XING

+0

A : ((10, '01 .01.2011 '), (20, '02 .02.2011'), (30, '02 .03.2011 '), 40, '04 .04.(10,101), (20, 102)) B : ((10,101), (20,102)) C :((10,101), (20,102), (30,101), (40,103)). – user3533397

1

시도해보십시오.

select max(aa.l_date) into l_date from A aa 
    where t_ref in 
    (SELECT t_ref from (select t_id t_ref,client_ref_ client_ref_ from C c 
          UNION 
         select t_ref t_ref,client_ref_ client_ref_ from B b) 
         tmp where tmp.client_ref = client_ref_) 
return l_date; 
+0

UNION이 필요하지 않습니다. 어떤 경우에도 C의 모든 레코드와'client_ref_'로 연결된 B의 모든 레코드를 반환하지만, B가 존재한다면 레코드가 필요하고 존재하지 않으면 C의 레코드가 필요합니다. – user3533397

+0

무슨 뜻입니까? by exist .. 3 개의 테이블 모두에서 샘플 데이터를 공유 할 수 있습니까? – Ravi

+0

테이블 B에'client_ref_'로 연결된 행이 있다면, 나는 그것을 필요로합니다. B에'client_ref_ '로 연결된 행이 없다면, C에서'client_ref_'로 연결된 모든 행을 선택해야합니다. – user3533397