2017-02-24 1 views
1

매개 변수 (매개 변수는 기본적으로 999)를 기반으로 행을 복제하려고합니다. 열 및 ID. 예를 들어 아래 샘플에서 임계 값은 999이고, ID가 ParamComp = 999 인 행과 ParamComp <>999 인 행이있는 경우 ParamComp <>999이있는 행의 경우 ColVal이 ParamComp = 999 인 새 레코드를 만들어야합니다.열을 기준으로 중복 행 oracle

ID에 ParamComp = 999 만있는 행이 있으면 대상에 직접로드하면됩니다 (중복 논리가 필요 없음). 아이디만을 ParamComp <> 999로 행이 경우

또한 단지

id ParamComp ColVal 
1 999   a 
1 80   b 
2 999   c 
3 85   d 

대상 데이터

직접 (중복되지 로직이 필요하지 않다) 타겟

입력 데이터로드

id ParamComp ColVal 1 999 a 1 80 b 1 80 a 2 999 c 3 85 d 
+0

샘플 데이터가 지정한 규칙을 따르지 않는다고 생각합니다. 그렇다면'id = 1'은 999를 갖는 두 개의 행을 가질 것입니다. 질문을 명확히하십시오. –

+0

"열 복제"라고 말하면 행을 의미합니까? 생성 된 추가 열은 표시되지 않습니다. 그런 다음 : 기존 행을 기반으로 새 행을 만들지 만 ParamComp 값이 다른 경우 "중복"도 아닙니다. 그리고 제목에서 : 관계형 데이터베이스는 "레코드"보다는 "행"을 가지고 있습니다. – mathguy

+0

@GordonLinoff ID의 경우 999가 ColVal 값 999에 따라 다른 행이 복제됩니다 (ID에 ParamComp 값이 '999'이고 999가 아닌 값인 경우). –

답변

1

(또는 빠른하지 않을 수 있음) 고든의 대답에 대한 대안과 같이, 부분 간은 2 행 더미 "테이블"에 가입하는 것입니다 :

WITH your_table AS (SELECT 1 ID, 999 paramcomp, 'a' colval FROM dual UNION ALL 
        SELECT 1 ID, 80 paramcomp, 'b' colval FROM dual UNION ALL 
        SELECT 2 ID, 999 paramcomp, 'c' colval FROM dual UNION ALL 
        SELECT 3 ID, 85 paramcomp, 'd' colval FROM dual UNION ALL 
        SELECT 4 ID, 999 paramcomp, 'e' colval FROM dual UNION ALL 
        SELECT 4 ID, 75 paramcomp, 'f' colval FROM dual UNION ALL 
        SELECT 4 ID, 70 paramcomp, 'g' colval FROM dual) 
-- end of mimicking your table; see SQL below: 
SELECT yt.ID, 
     yt.paramcomp, 
     case WHEN dummy.id = 1 THEN yt.colval 
      WHEN dummy.id = 2 THEN yt.paramcomp_999_colval 
     END colval 
FROM (SELECT ID, 
       paramcomp, 
       colval, 
       MAX(CASE WHEN paramcomp = 999 THEN colval END) OVER (PARTITION BY ID) paramcomp_999_colval 
     FROM your_table) yt 
     INNER JOIN (SELECT 1 ID FROM dual UNION ALL 
        SELECT 2 ID FROM dual) dummy ON dummy.id = 1 -- ensures every yt row is returned 
                OR (dummy.id = 2 
                 AND paramcomp_999_colval IS NOT NULL 
                 AND yt.paramcomp != 999) -- returns an extra row if the 999 paramcomp row exists but the current row isn't 999 
ORDER BY yt.ID, yt.paramcomp DESC, yt.colval; 

     ID PARAMCOMP COLVAL 
---------- ---------- ------ 
     1  999 a 
     1   80 b 
     1   80 a 
     2  999 c 
     3   85 d 
     4  999 e 
     4   75 e 
     4   75 f 
     4   70 g 
     4   70 e 

이 있다고 가정 오직 하나의 999 paramcomp 행 (예 : (id, paramcomp)에 대한 고유 제한 조건이 있음).

데이터와 성능면에서 가장 뛰어난 결과를 보려면 고든의 답변을 테스트해야합니다.


ETA : 당신이 비교 여기 고든의 대답의 고정 된 버전입니다 :

select id, paramcomp, colval 
from your_table 
union all 
select id, paramcomp, paramcomp_999_colval colval 
from (select yt.*, MAX(CASE WHEN paramcomp = 999 THEN colval END) OVER (PARTITION BY ID) paramcomp_999_colval 
     from your_table yt 
    ) t 
where paramcomp_999_colval IS NOT NULL and paramcomp <> 999 
ORDER BY ID, paramcomp DESC, colval; 

, η2 :

당신 경우 : 더미 테이블의 사용을 더 설명 테이블의 모든 행을 복제하려면 다음과 같이 두 행이있는 테이블/하위 쿼리에 대한 교차 조인을 수행하십시오.

SELECT * 
FROM your_table yt 
CROSS JOIN (SELECT 1 ID FROM dual UNION ALL 
      SELECT 2 ID FROM dual) dummy; 

     ID PARAMCOMP COLVAL   ID 
---------- ---------- ------ ---------- 
     1  999 a    1 
     1   80 b    1 
     2  999 c    1 
     3   85 d    1 
     4  999 e    1 
     4   75 f    1 
     4   70 g    1 
     1  999 a    2 
     1   80 b    2 
     2  999 c    2 
     3   85 d    2 
     4  999 e    2 
     4   75 f    2 
     4   70 g    2 

그러나 중복 행이 항상 나타나기를 원하지는 않으므로 조금 선택적으로 내부 조인을 수행해야합니다. 내 초기 답변에서 내부 조인을 무너 뜨릴 것이므로 조금 더 잘하고 있는지 잘 볼 수 있습니다.

우선, 여기의 부분 년대 그 your_table의 각 행이 반환되는 것을 보장 가입 :

SELECT * 
FROM your_table yt 
INNER JOIN (SELECT 1 ID FROM dual UNION ALL 
      SELECT 2 ID FROM dual) dummy ON dummy.id = 1; 

     ID PARAMCOMP COLVAL   ID 
---------- ---------- ------ ---------- 
     1  999 a    1 
     1   80 b    1 
     2  999 c    1 
     3   85 d    1 
     4  999 e    1 
     4   75 f    1 
     4   70 g    1 

다음, 여기가 그

SELECT * 
FROM your_table yt 
INNER JOIN (SELECT 1 ID FROM dual UNION ALL 
      SELECT 2 ID FROM dual) dummy ON dummy.id = 2 
              AND yt.paramcomp != 999; 

     ID PARAMCOMP COLVAL   ID 
---------- ---------- ------ ---------- 
     1   80 b    2 
     3   85 d    2 
     4   75 f    2 
     4   70 g    2 

당신을 연결하는 선택적 보장 가입의 일부 이 두 번째 부분에서 우리가 아직 id = 3 행을 얻었음을 알 수 있습니다. 그래서 위의 마지막 대답에서 paramcomp = 999 행의 colval이 조건부 최대 분석 함수를 사용하여 모든 행에 대해 반환되고 반환된다는 것을 알았습니다. 그런 다음 두 번째 조인 조건 부분에 추가하여 999 colval을 갖는 행만 반환합니다 (값이없는 경우 999 행이 존재하지 않는다고 가정합니다). 이것은 colval이 항상 999 행에 존재한다고 가정합니다.

+0

Gordon의 대답이 원하는 출력을 제공하지 못했기 때문에 999 자체로 레코드를 복제하고 999 레코드가 아닌 colval을 복사했습니다. 당신의 대답은 Working d가 원하는 출력을 제공합니다. 성능을 비교할 수 있도록 고든의 답변을 수정하기위한 해결 방법이 있습니까? –

+0

왜 ID 1과 2가있는 더미 테이블을 사용하고 있습니까? 도와 주실 수 있습니까? –

+1

Gordon의 답변이 제대로 작동하도록 답변을 업데이트했습니다. – Boneist

0

999가 0123의 최대 값이라고 가정하면이면 분석 함수와 union all이 문제를 해결할 수 있습니다. 텍스트에 지정하는 규칙에 따라 다음과 같이됩니다.

select id, paramcomp, colval 
from t 
union all 
select id, 999 as paramcomp, colval 
from (select t.*, max(paramcomp) over (partition by id) as max_paramcomp 
     from t 
    ) t 
where max_paramcomp = 999 and paramcomp <> 999; 

이것은 간단한 규칙 변형에 따라 쉽게 수정할 수 있습니다.

+0

이 표에는 임계 값으로 '999'만 있습니다. 또한 999 행이 중복되기를 원하지 않습니다. –

관련 문제