2015-01-28 3 views
2

이 쿼리를 올바르게 수행하는 방법에 대해서는 약간 혼란 스럽습니다. 나는 이렇게 생긴 탁자를 가지고있다. 지구 0은 모든 지구 (글로벌)에 적용되어야하는 가치를 나타냅니다.행을 결합하여 두 개의 데이터 열을 생성하십시오.

[ district ] [ code ] [ value ] 
    1   A   11 
    1   C   12 
    2   A   13 
    2   B   14 
    0   B   15 

각 지구에 "전역 값"을 결합하는 쿼리를 작성했습니다 (아래).

[ district ] [ code ] [ district value ] [ global value ] 
     1   A   11    null  -> row 1 
     1   B   null    15   -> row 2 
     1   C   12    null  -> row 3 
     2   A   13    null  -> row 4 
     2   B   14    15   -> row 5 
     2   C   null    null  -> row 6 (optional) 

가능한 모든 지구/코드 목록에 가입하여 만들었습니다.

select all_code.district, all_code.code, table_d.value, table_g.value 
    from (select distinct b.district, a.code 
      from temp_table a 
     inner join (select distinct district 
         from temp_table 
        where district <> 0) b 
      on 1 = 1) all_code 
    left join temp_table table_d 
    on table_d.code = all_code.code 
    and table_d.district = all_code.district 
    left join temp_table table_g 
    on table_g.code = all_code.code 
    and table_g.district = 0 

이 쿼리는 훌륭하게 작동하지만 꽤보기 흉하게 보입니다. 이 작업을 수행하는 더 좋은 방법이 있습니까? (행 # 6이 있는지 여부는 상관하지 않음).

다음은 필요한 경우 스크립트입니다.

create table temp_table 
(
    district VARCHAR2(5) not null, 
    code  VARCHAR2(5) not null, 
    value VARCHAR2(5) not null 
); 


insert into temp_table (district, code, value) 
values ('1', 'A', '11'); 
insert into temp_table (district, code, value) 
values ('1', 'C', '12'); 
insert into temp_table (district, code, value) 
values ('2', 'A', '13'); 
insert into temp_table (district, code, value) 
values ('2', 'B', '14'); 
insert into temp_table (district, code, value) 
values ('0', 'B', '15'); 
+0

을 당신이 원하는 것이 무엇 : 가입 불필요한 하위 쿼리를 제거하고 십자가에 대한 적절한 구문을 사용하는 것입니다 당신이 가지고있는 쿼리를 청소의 관점에서

는, 최고의 내가 올 수 지구 가치 대신 null 대신 표시 하시겠습니까? 궁극적으로 지구가 존재한다면 지구를, 지구가 존재하지 않는다면 지구를 원합니까? 왜냐하면 우리가 그 논리를 하나의 기둥에 적용 할 수 있기 때문입니다. –

+0

@GB 케이스 1 ~ 5 (옵션 6)를 질의의 출력으로 사용하려고합니다. 4 columns –

+0

OK 4 개의 열 - 기본 쿼리의 확장 일뿐입니다 - null 대신 원하는 것은 무엇입니까? 또는 원하는 경우 - case2의 문제점은 무엇입니까? –

답변

2

다음은 옵션들 중 하나입니다.

with DCodes(code) as(
    select 'A' from dual union all 
    select 'B' from dual union all 
    select 'C' from dual 
), 
DGlobal(code, value1) as(
    select code 
     , value 
    from temp_table 
    where district = 0 
) 
select tt.district 
    , dc.code 
    , tt.value 
    , dg.value1 as global_value 
    from temp_table tt 
     partition by(tt.district) 
     right join DCodes dc 
       on (dc.code = tt.code) 
     left join DGlobal dg 
       on (dg.code = dc.code) 
where tt.district != 0 
order by 1, 2 

결과 :

DISTRICT CODE VALUE GLOBAL_VALUE 
-------- ---- ----- ------------ 
1   A  11     
1   B   15   
1   C  12     
2   A  13     
2   B  14  15   
2   C      
1

내가 주장은 "추"많이 온다 당신이 10g에 있기 때문에 당신은 파티션 외부의 사용이 격차를 채우기 위해 (partition by() 절)에 가입 할 수 있습니다 districtcode에 대한 조회 표가 부족합니다. 이들에 대한 신뢰할 수있는 소스가 없으면 사용중인 값에서 하나를 조작해야합니다 (따라서 서브 쿼리는 distinct).

SELECT a.district, 
     b.code, 
     c.value1, 
     d.value1 
FROM  (SELECT DISTINCT district FROM temp_table WHERE district <> 0) a 
     CROSS JOIN (SELECT DISTINCT code FROM temp_table) b 
     LEFT JOIN temp_table c 
      ON b.code = c.code AND a.district = c.district 
     LEFT JOIN temp_table d 
      ON b.code = d.code AND d.district = 0 
ORDER BY district, code 
관련 문제