ORACLE/SCRIPT2010. 5. 28. 17:23
반응형
테이블의 특정 컬럼에
PK 나 UK 가 없을 때  테이블의 전체 또는 여러 컬럼들의 DATA들의 중복 확인

SELECT M_SSERVICE,M_SCODETYPE,M_SCODEVALUE,M_SDESC,M_SKIND,M_SDESCKOR,M_SPARENTCODE
FROM TCODEINFO
GROUP BY M_SSERVICE,M_SCODETYPE,M_SCODEVALUE,M_SDESC,M_SKIND,M_SDESCKOR,M_SPARENTCODE
HAVING COUNT(*)

/ 중복된 data확인 및 중복된 갯수 까지 출력
SELECT M_SSERVICE,M_SCODETYPE,M_SCODEVALUE,M_SDESC,M_SKIND,M_SDESCKOR,M_SPARENTCODE,COUNT(*)
FROM TCODEINFO
GROUP BY M_SSERVICE,M_SCODETYPE,M_SCODEVALUE,M_SDESC,M_SKIND,M_SDESCKOR,M_SPARENTCODE
HAVING COUNT(*)
반응형
Posted by [PineTree]
ORACLE/SQL2010. 4. 2. 16:58
반응형




이번달 퀴즈는 두가지 부정형 조인 NOT IN, NOT EXISTS 의 차이점을 설명하는것입니다.

문제를 명확히 하기 위해서 아래와 같은 상황을 고려하겠습니다.

테이블 : TEST1

     NO

Name

1

Lee

2

Kim

3

Park

<NULL>

Jang

<NULL>

<NULL>


테이블 : TEST2

NO

 

Name

 

1

Lee

2

Kim

3

Park

<NULL>

Jang

* <NULL>은 데이터가 NULL값인 경우입니다.


테스트 쿼리

1) NOT IN 의 경우

SELECT *
   FROM TEST1 A
  WHERE A.NO NOT IN (SELECT NO FROM TEST2)

2) NOT EXISTS 의 경우

SELECT *
   FROM TEST1 A
  WHERE NOT EXISTS (SELECT 1 FROM TEST2 B WHERE A.NO = B.NO)

위와 같은 상황에서 두 개의 테스트 쿼리를 실행하여 그 결과에 대해 왜 그렇게 나왔는지 설명하세요.



답안)

이번달 퀴즈의 문제는 NOT IN과 NOT EXISTS의 차이점이 무엇인가입니다.


1번, 2번의 경우에서 NO의 값 1,2,3은 모두 결과에 나오지 않습니다. 즉, TEST2에 속하지 않는것을 찾는것이므로 결과에 나오지 않게됩니다. 차이점은 NULL 값이 결과에 나오는가 아닌가에 있습니다.


NOT IN(1번)의 경우

where절의 조건이 맞는지 틀리는지를 찾는것입니다. 그런데 NULL은 조인에 참여하지 않기때문에 결과에서 빠집니다. 여기서 TEST1의 NULL값이 나오지 않은 이유는 IN 서브쿼리의 결과에 NULL유무에 영향을 받지 않습니다. 즉, TEST2의 NO컬럼에 NULL값이 없어도 TEST1의 NO컬럼의 NULL값은 결과에 나오지 않습니다.


NOT EXISTS(2번)의 경우

EXISTS는 서브쿼리가 TRUE인지 FALSE인지 체크하는 것이므로  NOT EXISTS는 서브쿼리가 FALSE이면 전체적으로 TRUE가 됩니다. 서브쿼리에서 TEST1과 TEST2의 조인시 NULL은 결과에서 빠지게 됩니다. 이것은 서브쿼리를 FALSE로 만들게 되고 전체적으로 TRUE가 되어 TEST1의 NULL값이 결과에 나오게 됩니다.


이번 퀴즈는 매우 쉬운것 같으나 자칫 잘못 생각할 수 있는 내용이기 때문에 퀴즈로 다루었습니다. 일반적으로 대용량을 처리할 때 성능상의 이유로 Hash Anti-Join, Merge Anti-Join으로 유도하기 위해 NOT EXISTS를 NOT IN으로 바꿔서 처리하기도 합니다. 이때 두 부정형 조인의 결과가 같다는 전제 조건이 있어야 합니다. 그러나 위에서와 같이 연결고리가 되는 컬럼의 값 중 NULL이 포함된 경우 결과가 다르다는것을 주의해야 합니다.



=========================================================================================================================
=========================================================================================================================



not in 과 not exists 차이점 / 부정형을 긍정으로 변경할때



일반적으로 대용량을 처리할때 성능상의 이유로 Not Exists로 되어 있는 것을


Not In으로 바꿔서 Hash나 Merge Anti Join으로 유도하는 경우가 있는데


이는 Not Exists와 Not In의 관계가 "="이 성립한다는 전제 조건에서 이루어 진다.


하지만 모든경우 Not Exists와 Not In의 관계가 "=" 성립하는지에 대한 의문에서


아래와 같이 테스트를 해보았습니다.


<결론>
   Not In 과 Not Exists는 다르다.
    + Not IN과 Not Exists의 차이점은 연결고리가 되는 컬럼의
      값중 null값을 처리하는 부분에서 차이가 난다.


<이유>
    + Not In 은 where 절의 조건이 만족하더라도
      연결고리 컬럼이 Null값을 가진 다면 결과에서 무조건 제외 된다.


    + Not Exists는 Not In과 달리 Null값을 가진 row들도 결과에 포함된다.


    + 간단히 생각해보면 in은 조건에 만족하는 row를 찾는 것이고
      exists는 exists이하 절이 true인지 아닌지를 체크하는 것이기 때문에
      연결고리 컬럼의 값이 null값을 가질때 null은 조인에 참여하지 못하기 때문에
      in은 조건에 만족하는 것을 찾을 수 없는 것이고
      exists는 false의 값을 return한다.
     
      따라서 연결고리 값이 null값을 가질때
      Not in은 조인 연산을 하지 않기 때문에 결과에서 제외되며
      Not Exists는 exists이하의 절이 false를 리턴하고 거기에 대한 Not이기 때문에
      결과적으로 true가 되어 결과에 포함된다.


<참고사항>


  1) 부정형을 긍정으로 변경할 때


    + Not In일 때는 상관 없지만 Not Exists일때는
      논리적으로 부정형을 긍정으로 변경 한 후 연결고리가 되는 컬럼이 null값 가질 경우에
      대해서 반드시 True가 되도록 처리해 줘야 된다.
    + 즉 null 값을 가지는 컬럼에 대해서도 결과에 포함 되도록 해야 된다.


  ex)
      SELECT :current_il,
             A.SNG_NO,
             A.SNG_SEQ,
             A.JI_HANDO,
             A.JI_HAN_BAL,
       FROM IRMS_SNG_MAS A
      WHERE A.WONJ_ST2 = '1'
        AND A.GAGIGONG_GB IN('2','3')
        AND NOT EXISTS(SELECT 'X'
                         FROM IRMS_SNG_MAS G
                        WHERE G.WONJ_ST2 = '1'
                          AND G.GAGIGONG_GB IN('2','3')
                          AND (G.MANGI_IL < :current_il AND NVL(G.SIL_BAL,0) = 0)
                          AND G.SNG_NO = A.SNG_NO
                          AND G.SNG_SEQ = A.SNG_SEQ)


   <부정형을 긍정형으로 변경>


     + MANGI_IL이 NULL값을 가질때 반드시 참이 되도록 해야 됨.
    
      SELECT :current_il,
             A.SNG_NO,
             A.SNG_SEQ,
             A.JI_HANDO,
             A.JI_HAN_BAL,
        FROM IRMS_SNG_MAS A
       WHERE A.WONJ_ST2 = '1'
         AND A.GAGIGONG_GB IN('2','3')
         AND NOT (NVL(A.MANGI_IL,'99991231') < :CURRENT_IL AND NVL(A.SIL_BAL,0) = 0)


<테스트 테이브>
TEST_AJ01
TEST_AJ02


<데이타>

TEST_AJ01
========================
NO        MARRY_DT
-------------------
1        20030405
2        20030405
3        20030405
<null>   <null>
<null>   20030408


TEST_AJ02
========================
NO        MARRY_DT
-------------------
1        20030405
2        20030405
3        20030405
<null>   20030408

# NULL값을 가진 컬럼의 값은 <null>이라고 표현하였음


<테스트 SQL문>
1)
    SELECT *
      FROM TEST_AJ01 A
     WHERE A.NO NOT IN (SELECT NO FROM TEST_AJ02)
  
   ==결과==  -- 0건
   No rows returned

2)
    SELECT *
      FROM TEST_AJ01 A
     WHERE NOT EXISTS (SELECT 'X' FROM TEST_AJ02 B WHERE A.NO = B.NO)

   ==결과==  -- 2건
   <null>    <null>
   <null>    20030408



==========================================================================================================================
==========================================================================================================================

TEST1 테이블의 데이터 중 TEST2에 속하지 않는 데이터만 가져오기 ( NOT IN, NOT EXISTS, JOIN, UNION 으로 해결 )

중복되지 않는 데이터만 가져와서 INSERT 하거나

중복되는 데이터만 가져와서 UPDATE 할 때 사용할 수도 있다.


CREATE TABLE TEST1 (
 IDX INTEGER,
 NAME VARCHAR(100)
)

CREATE TABLE TEST2 (
 IDX INTEGER,
 NAME VARCHAR(100)
)


INSERT INTO TEST1 VALUES (1, 'A')
INSERT INTO TEST1 VALUES (2, 'B')
INSERT INTO TEST1 VALUES (3, 'C')
INSERT INTO TEST1 VALUES (4, 'D')
INSERT INTO TEST1 VALUES (5, 'E')


INSERT INTO TEST2 VALUES (3, 'C')
INSERT INTO TEST2 VALUES (4, 'D')
INSERT INTO TEST2 VALUES (5, 'E')
INSERT INTO TEST2 VALUES (6, 'F')
INSERT INTO TEST2 VALUES (7, 'G')


SELECT * FROM TEST1
SELECT * FROM TEST2


-- NOT IN

SELECT *
  FROM TEST1
 WHERE IDX NOT IN (
SELECT IDX
  FROM TEST2 )


-- NOT EXISTS

SELECT *
  FROM TEST1 A
 WHERE NOT EXISTS (
SELECT *
  FROM TEST2 B
 WHERE A.IDX = B.IDX )


-- SYBASE JOIN
SELECT *
  FROM (
 SELECT A.*
   , B.IDX B_IDX
   FROM TEST1 A
      , TEST2 B
  WHERE A.IDX *= B.IDX
    ) A
   WHERE B_IDX IS NULL
 

-- ANSI JOIN

SELECT *
  FROM TEST1 A
  LEFT JOIN TEST2 B
    ON A.IDX = B.IDX
 WHERE B.IDX IS NULL
 

-- UNION ALL
SELECT A.IDX, A.NAME
  FROM (
  SELECT NAME
    , COUNT(*) CNT
    , COUNT(CASE WHEN GBN = 'A' THEN 1 END) A_CNT
    , IDX
    FROM (
    SELECT 'A' AS GBN
      , A.*
      FROM TEST1 A
    UNION ALL
    SELECT 'B'
      , B.*
      FROM TEST2 B
     ) A
   GROUP BY IDX, NAME
  ) A
 WHERE A.CNT < 2
   AND A_CNT = 1


출처 : http://blog.naver.com/tyboss?Redirect=Log&logNo=70051601411

반응형
Posted by [PineTree]
ORACLE/SQL2010. 1. 3. 14:10
반응형

오라클(Oracle)을 사용하여 다건조회(페이징) 처리를 해야하는 경우가 종종 있습니다.

물론 SQL 쿼리는 여러가지 방식으로 만들수 있고
다양한 방식이 존재하기에 어느하나가 정답이라고 할 수는 없습니다.


다만 실제 업무에서 개발중인 노하우를 공유하는 일환으로
다건조회(페이징) 처리시 DB의 성능 (대부분은 검색 속도와 관련된 부분이겠지요..)과 관련한 최적화된 쿼리 방식을 알려드리도록 하겠습니다.

이는 실제 DBA에게서 권고 받은 것이기 때문에 검증을 거쳤다고 할 수 있습니다.

자 그럼 아래를 참고하시어 최적화된 다건조회 쿼리 작성에 도움이 되시길 바랍니다.

## 1개 컬럼으로 페이징처리

SELECT *
FROM (
 SELECT ...
 WHERE ...
 AND A >= : io_nx_a
 ORDER BY A
)
WHERE ROWNUM <= 51

## 2개 컬럼으로 페이징처리

SELECT *
FROM (
SELECT ...
WHERE ///
AND A >= :io_nx_a
AND ( A > :io_nx_a
    OR ( A = :io_nx_a AND B >= :io_nx_b)
)
ORDER BY A, B)
WHERE ROWNUM <= 51

## 3개 이상의 다수개 컬럼으로 페이징처리

예) 5개 컬럼일 경우

SELECT *
FROM (
SELECT ...
WHERE ///
AND A >= :io_nx_a
AND (  A > :io_nx_a
     OR ( A = :io_nx_a AND B > :io_nx_b) )
     OR ( A = :io_nx_a AND B = :io_nx_b AND C > :io_nx_c)
     OR ( A = :io_nx_a AND B = :io_nx_b AND C = :io_nx_c AND D > :io_nx_d)
     OR ( A = :io_nx_a AND B = :io_nx_b AND C = :io_nx_c AND D = :io_nx_d AND E >= :io_nx_e)
)
ORDER BY A, B, C, D, E)
WHERE ROWNUM <= 51

(*) 제일 마지막의 OR에서만 '>='이고 나머지 OR에서는 '>'입니다.
반드시 ORDER BY에 기술된 컬럼들이 UNIQUE여야 하고 UNIQUE가 아닐 경우 이미 가이드 했던 것처럼 ROWID를 이용하셔야 합니다. SQL 가이드 참조

DBA의 말에 따르면 위와같은 방식으로
페이징 처리를 해주는 것이 DB(데이타베이스)의 성능향상에 도움이 된다더군요.

실제 예제는 아래처럼 사용됩니다.

SELECT /*+TB_CS_JH_CH_MCHTGRP_VS0001*/ *
 FROM
(
 SELECT
         a.mcht_grp_no,
         b.mcht_grpnm,
         a.mcht_no,
         c.mcht_mtalnm,
         a.apl_st_dt,
         a.apl_ed_dt
 FROM
       tb_cs_jh_ch_mchtgrp  a,
       tb_cs_jh_cm_mchtgrp  b,
       tb_cs_mc_cm_bsc      c
 WHERE a.mcht_no >= :mcht_no
   AND ( a.mcht_no > :mcht_no
          OR ( a.mcht_no = :mcht_no AND a.mcht_grp_no > :mcht_grp_no )
          OR ( a.mcht_no = :mcht_no AND a.mcht_grp_no = :mcht_grp_no  AND a.apl_st_dt >= :apl_st_dt )
           )

  AND  b.mcht_grp_no  =  a.mcht_grp_no 
     AND  b.apl_st_dt    <=  a.apl_st_dt
      AND  b.apl_ed_dt    >=  a.apl_ed_dt
     AND  c.mcht_no      =  a.mcht_no
 ORDER BY
       a.mcht_no, a.mcht_grp_no, a.apl_st_dt
)
WHERE ROWNUM <= 16

설명을 덧붙이자면
페이징시  메인 키가 되는 A >= :io_nx_a 의 인덱스서칭 시간만큼
OR을 동반한 올 시퀀스 서치시간을 줄여줄 수 있기 때문에 실제로 DB 검색시 속도향상 효과를 기대할 수 있습니다.

유용하게 사용하시기 바랍니다. ^^
반응형

'ORACLE > SQL' 카테고리의 다른 글

EXECUTE IMMEDIATE를 이용한 Dynamic SQL  (0) 2010.01.04
SQL *Plus 명령어와 SQL문 구분하기  (0) 2010.01.03
SQL TIP  (0) 2010.01.03
nvl2  (0) 2010.01.03
UNION  (0) 2010.01.03
Posted by [PineTree]
ORACLE/SCRIPT2009. 9. 11. 14:15
반응형
select *
from 테이블
where case when m_stpdesc < 'ㄱ' then SUBSTR(m_stpdesc, 1, 1)
            when ascii('ㄱ') <= ascii(m_stpdesc) and
                 ascii(m_stpdesc)<= ascii('ㅎ') then m_stpdesc
            when m_stpdesc < '나' then 'ㄱ'
            when m_stpdesc < '다' then 'ㄴ'
            when m_stpdesc < '라' then 'ㄷ'
            when m_stpdesc < '마' then 'ㄹ'
            when m_stpdesc < '바' then 'ㅁ'
            when m_stpdesc < '사' then 'ㅂ'
            when m_stpdesc < '아' then 'ㅅ'
            when m_stpdesc < '자' then 'ㅇ'
            when m_stpdesc < '차' then 'ㅈ'
            when m_stpdesc < '카' then 'ㅊ'
            when m_stpdesc < '타' then 'ㅋ'
            when m_stpdesc < '파' then 'ㅌ'
            when m_stpdesc < '하' then 'ㅍ'
            else                  'ㅎ'
       end = 'ㄹ' ;    <<=================찾고자하는 자음


m_stpdesc <<===========해당 컬럼

반응형
Posted by [PineTree]
ORACLE/SQL2009. 8. 10. 15:37
반응형


SELECT문은 데이터베이스로부터 저장되어 있는 데이터를 검색하는데 사용합니다.

[Syntax]


 · DISTINCT : 중복되는 행을 제거하는 옵션입니다.
 · *            :  테이블의 모든 column을 출력 합니다.
 · alias       :  해당 column에 대해서 다른 이름을 부여할 때 사용합니다.
 · table_name :  질의 대상 테이블명
 · WHERE    :   조건을 만족하는 행들만 검색
 · condition :  column, 표현식, 상수 및 비교 연산자
 · ORDER BY :   질의 결과 정렬을 위한 옵션(ASC:오름차순(Default),DESC내림차순)



 ☞ SQL문의 작성 방법

  - SQL 문장은 대소문자를 구별하지 않습니다.

  - SQL 문장은 한 줄 또는 여러 줄에 입력될 수 있습니다.

  - 일반적으로 키워드는 대문자로 입력합니다.
     다른 모든 단어, 즉 테이블 이름, 열 이름은 소문자로 입력합니다.(권장) 

  - 가장 최근의 명령어가 1개가 SQL buffer에 저장됩니다.

  - SQL문 마지막 절의 끝에 ";"를 기술하여 명령의 끝을 표시 합니다.
 


SQL>SELECT empno 사번, ename 성명
       FROM   emp
       WHERE  deptno = 10

      사번      성명
---------- ---------------
      7782      CLARK
      7839      KING
      7934      MILLER



empno와 ename 은 각각 사번과 성명이라는 컬럼 별칭(alias)으로 만들어 출력했습니다.
alias를 사용할 때 as라는 키워드를 사용해도 되고, 생략할수도 있습니다.


▒ WHERE절에 사용될 수 있는 SQL 연산자

 연산자

 설      명

 BETWEEN a AND b

 a와b사이의 데이터를 출력 합니다.(a, b값 포함)

 IN  (list)

 list의 값 중 어느 하나와 일치하는 데이터를 출력 합니다.

 LIKE

 문자 형태로 일치하는 데이터를 출력 합니다.(%, _사용)

 IS NULL

 NULL값을 가진 데이터를 출력 합니다.

 NOT BETWEEN a AND b

 a와b사이에 있지않은 데이터를 출력 합니다.(a, b값 포함하지 않음)

 NOT IN  (list)

 list의 값과 일치하지 않는 데이터를 출력 합니다.

 NOT LIKE

 문자 형태와 일치하지 않는 데이터를 출력 합니다.

 IS NOT NULL

 NULL값을 갖지 않는 데이터를 출력 합니다.




▣ IN, NOT IN 연산자



IN 연산자

SQL> SELECT empno, ename
         FROM  emp
         WHERE  empno IN (7900, 7934) ;

--> 사번이 7900, 7934번인 사원의 사번과 성명 출력

    EMPNO    ENAME
 --------- -------------
     7934      MILLER
     7900      JAMES

2 개의 행이 선택되었습니다.

 

NOT IN 연산자

SQL> SELECT empno, ename
         FROM  emp
         WHERE  empno NOT IN (7900, 7934);

--> 사번이 7900, 7934번이 아닌 사원의 사번과 성명 출력

     EMPNO ENAME
-------- --------------
    7369 SMITH
    7499 ALLEN
    7521 WARD
    7566 JONES 
    7654 MARTIN
    7698 BLAKE
    ............................
13 개의 행이 선택되었습니다.



BETWEEN연산자(AND를 이용해 두 조건을 결합한 검색과 같은 결과값을 보여줍니다.)

BETWEEN 연산자

SQL>  SELECT empno, ename
          FROM  emp
          WHERE  sal BETWEEN  3000 AND 5000 ;

--> 급여가 3000에서 5000사이인 사원만 보여줍니다.

     EMPNO ENAME
   ---------- ------
      7788 SCOTT
      7839 KING
      7902 FORD  
3 개의 행이 선택되었습니다.



LIKE 연산자

 - 검색 STRING 값에 대한 와일드 카드 검색을 위해서 LIKE연산자를 사용 합니다.
 - % :  여러개의 문자열을 나타내는 와일드 카드
 - _ : 단 하나의 문자를 나타내는 와일드 카드
 - ESCAPE : 와일드 카드 문자를 일반문자 처럼 사용하고 싶은 경우에 사용합니다.
   ☞ WHERE name LIKE ’%a\_y%’ ESCAPE ’\’ ;

구 분

설 명

LIKE ’A%’

컬럼이 ’A’로 시작하는 데이터들만 검색됩니다.

LIKE ’%A’

컬럼이 ’A’로 끝나는 테이터들만 검색됩니다.

LIKE ’%KIM%’

컬럼에 ’KIM’ 문자가 있는 데이터 들만 검색됩니다.

LIKE ’%K%I%’

컬럼에 ’K’ 문자와 ’I’문자가 있는 데이터 들만 검색됩니다.

LIKE ’_A%’

컬럼에 ’A’문자가 두 번째 위치한 데이터 들만 검색됩니다.


- LIKE 연산자는 대소문자를 구분합니다.
- Upper()함수를 이용해 대소문자 구분없이 출력할수 있습니다.


SQL>SELECT empno, ename
        FROM  emp
        WHERE  UPPER(ename) like%K%’;

EMPNO ENAME
------- -----------
   7698 BLAKE
   7782 CLARK
   7839 KING

’K’ 문자가 들어있는 사원 정보를 보여줍니다.
upper()라는 함수는 k가 들어가 있는 것도 대문자 ’K’로 인식하기 때문에 데이터들을 보여줍니다.



※ ’_’를 이용한 LIKE검색

SQL>SELECT empno, ename
        FROM  emp
        WHERE  UPPER(ename) like_I%’

  EMPNO ENAME
------- ----------
   7839 KING
   7934 MILLER

※ ’_’는 한 문자를 나타냅니다.
   ’I’ 문자가 두 번째 문자에 위치한 사원들의 정보를 보여줍니다.

 



ORDER BY
(ASC[오름차순], DESC[내림차순])
  ORDER BY 절은 데이터의 정렬을 위해 사용합니다.  

SQL> SELECT empno, ename
         FROM  emp
         WHERE  deptno = 30
         ORDER BY ename ASC;

   EMPNO ENAME
-------- ---------
    7499 ALLEN
    7698 BLAKE
    7900 JAMES
    7654 MARTIN
    7844 TURNER
    7521 WARD

SQL> SELECT empno, ename
         FROM  emp
         WHERE  deptno = 30
         ORDER BY 2

위 두 개의 쿼리는 동일한 결과를 가져 옵니다.
 


  ================================================
    * 데이터베이스 정보공유 커뮤니티 oracleclub.com
    * 강좌 작성자 : 김정식 (oramaster _at_ naver.com)
  ================================================
반응형

'ORACLE > SQL' 카테고리의 다른 글

ROLLUP , CUBE , GROUPING  (0) 2009.09.02
Oracle 널값(null)에 대하여 정리  (0) 2009.08.21
DBMS에 따른 날짜포맷 변환  (0) 2009.08.07
CUBE 함수  (0) 2009.07.08
ROLLUP 함수  (0) 2009.07.08
Posted by [PineTree]
ORACLE/SQL2009. 2. 24. 10:54
반응형


서로다른 DB사이에 DB링크로 연결된 두개의 테이블을 SRC 테이블에서 TARGET테이블로 COPY하는 INSERT스크립트 생성 SQL

개념은 UNION ALL을 이용해서 명령어를 APPEND하는 방식

앞이나 뒤에 필요한 SQL COMMAND를 추가할 수 있다.

 

나중에 프로시져로 만들어야겠다.

---------------------------------------------------------------------------------------

SELECT 'DELETE ' || TNAME || ';' FROM TAB WHERE TNAME = '&nbsp'
UNION ALL
SELECT 'INSERT /*+ append PARALLEL*/ INTO   '|| TNAME || ' (' NAME FROM TAB WHERE TNAME = '&nbsp'
UNION ALL
SELECT NAME FROM (
 SELECT '          ' ||DECODE(COLUMN_ID,1,'',',')||COLUMN_NAME NAME
 FROM user_tab_columns T1
 WHERE 1=1
 AND TABLE_NAME = '&nbsp'
 ORDER BY T1.COLUMN_ID
)
UNION ALL
SELECT ')' NAME FROM DUAL
UNION ALL
SELECT 'SELECT ' NAME FROM DUAL
UNION ALL
SELECT NAME FROM (
 SELECT '          ' ||DECODE(COLUMN_ID,1,'',',')||COLUMN_NAME NAME
 FROM user_tab_columns T1
 WHERE 1=1
 AND TABLE_NAME = '&nbsp'
 ORDER BY T1.COLUMN_ID
)
UNION ALL
SELECT 'FROM  '|| TNAME || '@DIMS_REAL;' NAME FROM TAB WHERE TNAME = '&nbsp'
UNION ALL
SELECT 'COMMIT;' FROM DUAL


반응형
Posted by [PineTree]
ORACLE/SQL2009. 2. 24. 10:44
반응형

SYS_CONNECT_BY_PATH()함수를 BOM구조에서뿐만 아니라 BOM구조가 아닌경우에도 사용할 수 있다.

 

세로로 되어있는 형태

 


원하는 형태 : 가로로 출력

 
 
성분코드를 그룹코드별로 화면에 가로로 출력하고 싶을때 사용하는 SQL
-- 테이블 생성 스크립트
DROP TABLE ZZ_TAB1;
CREATE TABLE ZZ_TAB1 (
 ITEM_SEQ NUMBER ,
 TOTAL_SEQ NUMBER,
 INGR_SEQ NUMBER,
 INGR_CODE VARCHAR2(6),
 INGR_QTY VARCHAR2(10),
 COSMETIC_MIX_GROUP_SEQ NUMBER,
 SORT_KEY NUMBER
)
;
DROP TABLE DRC_INGR
CREATE TABLE DRC_INGR (
 INGR_CODE VARCHAR2(6),
 INGR_KORNAME VARCHAR2(50)
);
 
-- 테스트 데이터 생성
INSERT INTO ZZ_TAB1 VALUES (2006262803,1,1,'008186','0.291',1,2);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,2,'008187','0.291',1,1);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,3,'008188','0.291',1,3);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,4,'008181','0.291',1,4);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,5,'008182','0.301',2,1);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,6,'008183','0.301',2,2);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,7,'008184','0.301',2,4);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,8,'008185','0.301',2,5);
INSERT INTO ZZ_TAB1 VALUES(2006262803,1,9,'008189','0.301',2,3);
 
INSERT INTO DRC_INGR VALUES ('008187','동충하초');
INSERT INTO DRC_INGR VALUES ('008186','동청');
INSERT INTO DRC_INGR VALUES ('008188','두시');
INSERT INTO DRC_INGR VALUES ('008181','대청엽');
INSERT INTO DRC_INGR VALUES ('008182','대풍자');
INSERT INTO DRC_INGR VALUES ('008183','동과자');
INSERT INTO DRC_INGR VALUES ('008189','두충엽');
INSERT INTO DRC_INGR VALUES ('008184','동과피');
INSERT INTO DRC_INGR VALUES ('008185','동규자');
COMMIT;

SELECT       ITEM_SEQ
                 ,TOTAL_SEQ
                 ,COSMETIC_MIX_GROUP_SEQ
                 ,SUBSTR(MAX (SYS_CONNECT_BY_PATH (INGR_SEQ, '/')), 2) INGR_SEQ
                 ,SUBSTR(MAX (SYS_CONNECT_BY_PATH (INGR_CODE, '/')), 2) INGR_CODE
                 ,SUBSTR (MAX (SYS_CONNECT_BY_PATH (T1.INGR_KOR_NAME, '/')), 2)  INGR_KOR_NAME
                ,MAX(INGR_QTY) INGR_QTY
FROM   (
    SELECT  ITEM_SEQ,
                 TOTAL_SEQ,
                 INGR_SEQ,
                 T1.INGR_CODE,
                 T2.INGR_KOR_NAME,
                 INGR_QTY,
                 COSMETIC_MIX_GROUP_SEQ,
                 SORT_KEY RNUM  -- 칼럼에 소트키가 있을때
                 --ROW_NUMBER () OVER (PARTITION BY COSMETIC_MIX_GROUP_SEQ ORDER BY ROWNUM) rnum  -- 칼럼에 별도의 소트키가 없을때
   FROM  ZZ_TAB1 T1, DRC_INGR T2
   WHERE  T1.INGR_CODE = T2.INGR_CODE
         ) T1
START WITH RNUM = 1
CONNECT BY PRIOR RNUM = RNUM - 1 AND PRIOR COSMETIC_MIX_GROUP_SEQ = COSMETIC_MIX_GROUP_SEQ
  GROUP BY   ITEM_SEQ
         ,TOTAL_SEQ
         ,COSMETIC_MIX_GROUP_SEQ
;
반응형
Posted by [PineTree]