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 41543 게시물 읽기
No. 41543
UNION 대신 사용할 방법
작성자
초보자
작성일
2018-03-29 10:36ⓒ
2018-03-29 10:41ⓜ
조회수
6,457

 

SELECT A AS CODE, (SELECT COUNT(*) FROM 테이블1 WHERE 조건1) AS 카운트

FROM DUAL

UNION ALL

SELECT B AS CODE, (SELECT COUNT(*) FROM 테이블1 WHERE 조건2) AS 카운트

WHERE 조건2

FROM DUAL

 

데이터 가공을 위해서

이런식으로.. 같은 테이블에서 조건을 다르게해서

가져오는 코드명만 다르게 하고 싶을 경우에 UNION 대신 다른 효율적 방법이 있을까요??

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

SELECT code
     , COUNT(*) cnt
  FROM (SELECT CASE WHEN 조건1 THEN 'A'
                    WHEN 조건2 THEN 'B'
                END code
          FROM t
         WHERE 조건1
            OR 조건2
        )
 GROUP BY code
 ORDER BY code
;

마농(manon94)님이 2018-03-29 11:31에 작성한 댓글입니다.

 마농님 댓글 감사합니다.

해당쿼리로 작성해서 돌렸는데, 이상하게 UNION ALL 보다 시간이 2분이상 더 느리네요.

 

CASE WHEN 조건1.1 AND 조건1.2 AND 조건1.3 THEN 'A'

           WHEN 조건2.1 AND 조건2.2 AND 조건2.3 THEN 'B"

END CODE

FROM T

WHERE 조건1.1

AND 조건1.2

AND 조건1.3

OR 조건2.1

AND 조건2.2

AND 조건2.3

 

이런식으로 했습니다.

조건1, 조건2에 AND로 되어 있는 부분이 더 있어서 그런건지,

아니면 OR가 있어서 그런건지..흠..

 

그리고, 조건1.1~1.2 / 조건2.1~2.2 는 서로 같은 조건이고,

조건1.3 조건2.3만 다를경우에 좀더 간편하게 작성할 수 있는 방법이 있나요??

 

초보자님이 2018-03-29 13:48에 작성한 댓글입니다. Edit

AND 와 OR 가 공존할 때는 괄호에 유의해야 합니다.
공통 조건은 밖으로 빼고 개별 조건만 안으로 넣고.


SELECT *
  FROM t
 WHERE 조건1.1
   AND 조건1.2
   AND (조건1.3 OR 조건2.3)
;
 

마농(manon94)님이 2018-03-29 14:07에 작성한 댓글입니다.
이 댓글은 2018-03-29 14:07에 마지막으로 수정되었습니다.

 마농님 댓글 감사합니다!

알려주신대로, WHERE절에 공통조건은 밖으로 빼고, 개별조건은 안으로 넣었더니 시간이 조금 단축되었습니다. 

CASE WHEN 에서도 공통조건 밖으로 빼고 개별조건 안으로 넣으려니 문법상 틀리다고 나오네요.

CASE WHEN 조건1.1

           AND 조건1.2

           AND (조건1.3 THEN 'A' OR 조건 2.3 THEN 'B') END CODE

 

이런식으로 해봤거든요.

 

일단, 현재 상황은 WHERE절 공통조건 밖으로 뺀 결과와 UNION ALL로 개별쿼리 합친 결과 시간은

UNION ALL이 대략 2분정도 빠릅니다. 

왜그럴까요??

 

마농님 덕에 많은 것을 배우고있습니다.

초보자님이 2018-03-29 14:28에 작성한 댓글입니다. Edit

공통 조건을 밖으로 뺐으니 case 에는 개별 조건만 주면 됩니다.
성능이 느린 것은 실행계획을 비교해 보셔야 합니다.


SELECT code
     , COUNT(*) cnt
  FROM (SELECT CASE WHEN 조건1.3 THEN 'A'
                    WHEN 조건2.3 THEN 'B'
                END code
          FROM t
         WHERE 조건1.1
           AND 조건1.2
           AND (조건1.3 OR 조건2.3)
        )
 GROUP BY code
 ORDER BY code
;

마농(manon94)님이 2018-03-29 14:44에 작성한 댓글입니다.

마농님 답변 감사드립니다.

많은 배웠씁니다! 

초보자님이 2018-03-29 15:09에 작성한 댓글입니다. Edit

마농님.

SELECT A AS CODE, (SELECT COUNT(*) FROM 테이블1 WHERE 조건1) AS 카운트

FROM DUAL

UNION ALL

SELECT B AS CODE, (SELECT COUNT(*) FROM 테이블1 WHERE 조건2) AS 카운트

FROM DUAL

 

위 쿼리를 알려주신 CASE WHEN으로 바꿨을 때

COUNT(*)가 COUNT(필드명 or 특정조건)로 줄 경우에는 어떻게 달라지나요?

그리고, COUNT(DISTINCT(필드명 or 특정조건) 등도 궁금합니다.

 

case when에 distinct 등 해봐도 다 문법오류더라구요..

 

초보자님이 2018-03-29 17:14에 작성한 댓글입니다. Edit

질문이 계속 모호한 표현, 막연한 표현입니다.
조건1, 조건2, 특정조건, 필등명 등의 막연한 표현보다는
실제 사용하는 조건을 보여주는 방식으로 질문해 주세요.
컬럼1 = 1 AND 컬럼2 > 100 이런식으로 구체적으로 표현해 주세요.
A AS CODE 식의 잘못된 표현도 정확한 표현으로 고쳐주시구요.
case when에 distinct 등 해봐도 다 문법오류더라구요..라는 표현도
실제 사용하신 코드를 구체적으로 보여주셔야 합니다.
사용하신 조건들과 해당 조건컬럼에 대한 인덱스 정보도 있어야 합니다.

마농(manon94)님이 2018-03-29 18:12에 작성한 댓글입니다.
이 댓글은 2018-03-29 18:16에 마지막으로 수정되었습니다.

넵 마농님 죄송하고 답변감사합니다.

 

지금 쿼리는 

SELECT 'A' AS CODE, (SELECT COUNT(DISTINCT(A.B_C || '_' || nvl(A.B_D,  A.B_E))

                                          FROM TABLE A

                                          WHERE A.C = 'KR'

                                          AND A.D IN ('G', 'F', 'U') )

FROM DUAL

UNION ALL

SELECT 'B' AS CODE, (SELECT COUNT(DISTINCT('EU' || '_' || nvl(A.B_D, ''))

                                          FROM TABLE A

                                          WHERE A.C = 'KR'

                                          AND A.D IN ('K', 'E', 'U', I, O) )

FROM DUAL

UNION ALL

SELECT 'C' AS CODE, (SELECT COUNT(*)

 

                                          FROM TABLE A

                                          WHERE A.C = 'US'

                                          AND A.D IN ('A1', 'B2', 'C3') )

FROM DUAL

UNION ALL

 

SELECT 'C' AS CODE, (SELECT COUNT(*)

 

                                          FROM TABLE B

                                          WHERE B.NUMBER = '111'

                                          AND B.VERSION <> 'E'

FROM DUAL

 

.

.

.

위와같이 데이터 가공을 위해  UNION ALL로 이어갑니다.

바뀌는 것은 테이블명, COUNT(* or 컬럼명 or 조건식, DISTINCT) , 그 안에 WHERE 조건 등입니다.

 

CASE WHEN 을 이용해서는

SELECT CODE, COUNT(*) AS CNT

FROM (SELECT CASE WHEN A.CD = '01'  AND A.CC='E' THEN 'A'

                                       WHEN A.CD = '02' THEN 'B'

                                       WHEN A.CD = '03' THEN 'C'

                                      END CODE 

                  FROM TABLE A

                  WHERE A.CD = '01'

                      OR     A.CD = '02'

)

 

위처럼 테이블이 동일하고, COUNT(*)을 가져올 경우에는 알려주신대로 바꿔서 잘 되는데요.

 

테이블이 2개이상이거나, COUNT(*) COUNT(DISTINCT(A ||  _  || nvl(B)) 이런식으로 섞여있으면 어떻게 처리해야 할지 궁금합니다..

혹은 섞여있지 않더라도, COUNT(DISTINCT)을 처리할 땐 어떻게 해야할지 모르겠어서요.

 

ㅜㅜ 횡설수설하고있는 느낌인데 죄송합니다.

 

              

              

 

 

 

 

 

 

 

초보자님이 2018-03-30 09:25에 작성한 댓글입니다. Edit

조건 명확하게 표시해 주신거 맞나요?
A 와 B 가 겹치는 부분(U)이 있네요?
I 와  O 는 따옴표도 없고???
컬럼 및 조건을 명확하게 해주셔야
공통 조건인지? 개별조건인지?
집합이 겹치는지 안겹치는지 등을 파악할 수 있습니다.

마농(manon94)님이 2018-03-30 11:10에 작성한 댓글입니다.

SELECT CHR(lv + 64) code
     , DECODE(lv, 1, cnt1, 2, cnt2, 3, cnt3) cnt
  FROM (SELECT LEVEL lv FROM dual CONNECT BY LEVEL <= 3)
     , (SELECT COUNT(DISTINCT
                     CASE WHEN c = 'KR'
                           AND d IN ('G', 'F', 'U')
                          THEN b_c ||'_'|| NVL(b_d, b_e)
                      END ) cnt1
             , COUNT(DISTINCT
                     CASE WHEN c = 'KR'
                           AND d IN ('K', 'E', 'U', 'I', 'O')
                          THEN 'EU_' || b_d
                      END ) cnt2
             , COUNT(CASE WHEN c = 'US'
                           AND d IN ('A1', 'B2', 'C3')
                          THEN 1
                      END ) cnt3
          FROM table_a
         WHERE c IN ('KR', 'US')
           AND d IN ('G', 'F', 'U', 'K', 'E', 'I', 'O', 'A1', 'B2', 'C3')
        )
 UNION ALL
SELECT 'D' code
     , COUNT(*) cnt
  FROM table_b
 WHERE number = '111'
   AND version <> 'E'
;

마농(manon94)님이 2018-03-30 11:41에 작성한 댓글입니다.
이 댓글은 2018-03-30 11:43에 마지막으로 수정되었습니다.

마농님 감사합니다.!

마농님 덕분에 정말 많은 공부가 되었습니다!!

초보자님이 2018-03-30 14:42에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
41546기준일자별 쿼리 문의드립니다. [2]
량디
2018-04-06
5560
41545파라미터 분리하기 [2]
궁금
2018-04-04
5884
41544cursor 문의 (마농님 부탁드립니다 !) [2]
Tevere
2018-04-02
5894
41543UNION 대신 사용할 방법 [12]
초보자
2018-03-29
6457
41541세로 데이터를 가로로 만들 때 [4]
초보자
2018-03-27
20225
41540근무기간 구하기 [2]
IT재벌
2018-03-26
5953
41539쿼리 질문드려요~ 답변부탁드립니다. [1]
잘될거다
2018-03-23
5768
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.016초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다