database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 40783 게시물 읽기
No. 40783
특정값을 기준으로 차이점 비교하는 쿼리 질문드립니다.
작성자
choiksn
작성일
2015-04-28 13:51ⓒ
2015-04-28 16:15ⓜ
조회수
15,450

바로 전에 올렸던 질문이 너무 모호해서 다시 작성합니다. ^^;;

 

환경은 Oracle 10g 입니다.

 

with user_data as

(

select 'A' user_id, 'TB_A' user_cat from dual union

select 'B' user_id, 'TB_A' user_cat from dual union

select 'C' user_id, 'TB_A' user_cat from dual union

select 'D' user_id, 'TB_A' user_cat from dual union

select 'E' user_id, 'TB_A' user_cat from dual union

select 'F' user_id, 'TB_A' user_cat from dual union

select 'A' user_id, 'TB_B' user_cat from dual union

select 'B' user_id, 'TB_B' user_cat from dual union

select 'E' user_id, 'TB_B' user_cat from dual union

select 'F' user_id, 'TB_B' user_cat from dual union

select 'A' user_id, 'TB_C' user_cat from dual union

select 'B' user_id, 'TB_C' user_cat from dual union

select 'C' user_id, 'TB_C' user_cat from dual union

select 'K' user_id, 'TB_C' user_cat from dual

)

select *

from user_data;

 

위와 같은 사용자 데이터가 있습니다.

설명을 위해서 3개의 테이블을 user_cat로 구분하여 하나로 합쳤습니다.

 

원하는 결과는 아래와 같습니다.

즉 user_cat 별로 user_id의 누락개수를 아래와 같은 테이블처럼 표현하고 싶습니다.

기준은 user_cat가 됩니다.

예를 들어, TB_A를 기준으로 하면, TB_B는 'C', 'D' user_id가 없기 때문에 차이는 -2 입니다. TB_C는 'D', 'E', 'F' 사용자가 없기때문에 -3입니다.

결과는 아래와 같지만, 어떤 user_id가 없는지도 알아야 합니다.

 

user_cat | TB_A | TB_B | TB_C |

TB_A | 0 | -2 | -3 |

TB_B | 0 | 0 | -2 |

TB_C | -1 | -2 | 0 |

 

고수분들의 고견을 기다리겠습니다.

 

** 추가 **

각 테이블에 User_id를 기준으로 차이점을 알고 싶은게 제 질문의 핵심입니다.

 

이 글에 대한 댓글이 총 6건 있습니다.

SELECT user_cat
     , tb_a
     , tb_b
     , tb_c
  FROM (SELECT user_cat
             , REPLACE(WM_CONCAT(user_id), ',') x
          FROM user_data
         GROUP BY user_cat
        )
 MODEL
 DIMENSION BY (user_cat)
 MEASURES (x, 0 tb_a, 0 tb_b, 0 tb_c)
 RULES
 ( tb_a[ANY] = -NVL(LENGTH(REGEXP_REPLACE(x[CV()], '['||x['TB_A']||']')), 0)
 , tb_b[ANY] = -NVL(LENGTH(REGEXP_REPLACE(x[CV()], '['||x['TB_B']||']')), 0)
 , tb_c[ANY] = -NVL(LENGTH(REGEXP_REPLACE(x[CV()], '['||x['TB_C']||']')), 0)
 )
;

마농(manon94)님이 2015-04-28 16:17에 작성한 댓글입니다.
이 댓글은 2015-04-28 16:18에 마지막으로 수정되었습니다.

마농님 답글 주심에 감사드립니다.

지금 당장은 제시해주신 내용이 무엇인지도 잘 모르고,

아래와 같은 오류가 발생하긴 하지만,

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

ORA-00932: 일관성 없는 데이터 유형: -이(가) 필요하지만 CLOB임

00932. 00000 - "inconsistent datatypes: expected %s got %s"

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

좋은 공부가 될것으로 생각하고, 열심히 파보겠습니다.

 

매번 많이 배우고, 도전받고 갑니다.

다시한번 감사드립니다.

 

다른 분들께서도 아래 참고하셔서 공부해보시면 좋겠습니다.

http://docs.oracle.com/cd/B19306_01/server.102/b14223/sqlmodel.htm

choiksn님이 2015-04-28 16:32에 작성한 댓글입니다. Edit

SELECT user_cat
     , COUNT(DECODE(x, 'TB_A', 1)) - COUNT(DECODE(lv, 1, 1)) tb_a
     , COUNT(DECODE(x, 'TB_B', 1)) - COUNT(DECODE(lv, 1, 1)) tb_b
     , COUNT(DECODE(x, 'TB_C', 1)) - COUNT(DECODE(lv, 1, 1)) tb_c
  FROM (SELECT CONNECT_BY_ROOT user_cat user_cat
             , user_cat x
             , LEVEL lv
          FROM user_data
         CONNECT BY PRIOR user_cat != user_cat
           AND PRIOR user_id = user_id
           AND LEVEL <= 2
        )
 GROUP BY user_cat
;

마농(manon94)님이 2015-04-28 16:49에 작성한 댓글입니다.

추가 답변 감사드립니다.

 

시간되시면, 어떤원리인지 도 좀 간단히 설명해 주시면 배우는데 많은 도움될것 같습니다.

염치없지만, 열심히 배우겠습니다. ^^

 

choiksn님이 2015-04-28 17:00에 작성한 댓글입니다.
이 댓글은 2015-04-28 17:33에 마지막으로 수정되었습니다. Edit

○ 1번 : 문자열끼리 비교하여 측정하는 방법입니다.
  1. 그룹바이로 문자열을 연결시키고
  2. 모델절을 이용하여 각 행의 값을 참조할수 있으며
  3. 정규표현식을 이용하여 서로 매치되는 값을 지웁니다.
  4. 지우고 남은 문자의 길이가 바로 원하는 결과입니다.
  5. wm_concat 사용시 clob 문제가 발생되는 환경도 드물게 있더군요.
○ 2번 : 매치되는 문자를 계층구조로 연결해 카운트하는 방법
  1. Start With 절이 없으므로 모든 행이 루트가 됩니다.
  2. Connect By 구문으로 계층 구조로 연결합니다.
     연결조건은 user_cat 이 다르고 user_id 가 같은거
     계층의 Level 을 2로 제한합니다.
  3. 결과를 살펴보면
     TB_A 의 경우 1레벨은 TB_A(A,B,C,D,E,F) 6건이 존재합니다.
     2레벨은 user_cat 이 다른 TB_B, TB_C 와 연결되며
     user_id 가 같은 TB_B(A,B,C,D) 4건, TB_C(A,B,C) 3건이 연결됩니다.
     TB_A 건수 - 1레벨건수 = 6 - 6 =  0
     TB_B 건수 - 1레벨건수 = 4 - 6 = -2
     TB_C 건수 - 1레벨건수 = 3 - 6 = -3
  4. Connect_by_root 를 이용하여 Group BY 합니다.

마농(manon94)님이 2015-04-29 09:07에 작성한 댓글입니다.

마농님,

 

문제도 해결해주시고,

염치없는 요청이었음에도 친절한 설명까지....

 

SQL문도 배웠지만, 재능기부의 본보기를 보게되었네요.

 

감.사.합.니.다.

 

choiksn님이 2015-04-30 11:10에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
40786ora-01654발생 후 사이즈 증가 느려짐
mossmin
2015-04-30
6795
40785union시 [2]
천랑성
2015-04-29
6509
40784특정조건에서의 Select Query 지연현상 [1]
최영수
2015-04-29
6862
40783특정값을 기준으로 차이점 비교하는 쿼리 질문드립니다. [6]
choiksn
2015-04-28
15450
40781숫자구간할당 [2]
쿼리OTL
2015-04-27
7091
40778dbca로 dbID를 생성할려고 하는데 질문좀 할게요
dbhelp
2015-04-20
6937
40777숫자 구간 중복 검사 쿼리 문의 드립니다. [2]
쿼리OTL
2015-04-20
7000
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.019초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다