집계값 내기 0 7 1,626

by 달타냥 [2016.11.04 00:17:11]


몇시간째 해결이 안되는 문제가 있어 글 올립니다.

서울, 부산 등 대도시 밑에 대리점이 있고 각 대리점은 회원을 두고 있습니다.

그리고 그 회원들은 여러 대리점에 동시에 회원으로 가입이 가능하게 되어 있습니다.

문제는 회원 번,호를 기준으로 구별 유니크하게 회원수와 대도시 기준으로 유니크하게 회원수도 동시에 내야 합니다.

예를들어 한 회원이 서대문, 종로에 회원으로 가입되어 있으면 서대문, 종로 대리점별로 한명씩 회원으로 집계가

되지만 서울 본사 기준으로는 한명만이 집계가 되어야 합니다.

즉 전체별 대리점별 집계를 동시에 내야 하는 경우입니다.

count(distinct 회원번호), count(distinct 회원번호) over(partition... 으로 하려하는데 원하는 값이 안나오네요.

구분 대리점 광역시_회원수 대리점_회원수
서울 서울_대리점1 5 4
서울 서울_대리점2 5 3
서울 서울_대리점3 5 2
서울 서울_대리점4 5 7
부산 부산_대리점1 8 5
부산 부산_대리점2 8 3
부산 부산_대리점3 8 7
부산 부산_대리점4 8 21
부산 부산_대리점5 8 9
부산 부산_대리점6 8 7

이런식으로 되어야 하는데 조언을 요청드립니다.

그런데 이게 가능한가요?

감사합니다.

by jkson [2016.11.04 08:23:12]
WITH T AS
(
SELECT '서울' GB1, '서대문' GB2, '1' ID FROM DUAL UNION ALL
SELECT '서울' GB1, '서대문' GB2, '2' ID FROM DUAL UNION ALL
SELECT '서울' GB1, '서대문' GB2, '3' ID FROM DUAL UNION ALL
SELECT '서울' GB1, '종로' GB2, '1' ID FROM DUAL UNION ALL
SELECT '서울' GB1, '종로' GB2, '2' ID FROM DUAL UNION ALL
SELECT '부산' GB1, '북구' GB2, '5' ID FROM DUAL UNION ALL
SELECT '부산' GB1, '북구' GB2, '6' ID FROM DUAL UNION ALL
SELECT '부산' GB1, '동래구' GB2, '6' ID FROM DUAL UNION ALL
SELECT '서울' GB1, '동대문' GB2, '4' ID FROM DUAL
)
SELECT b.gb1
     , b.gb2
     , a.cnt1
     , b.cnt2
  FROM ( SELECT gb1, COUNT( DISTINCT id ) cnt1
           FROM t
          GROUP BY gb1 ) a
     , ( SELECT gb1, gb2, COUNT( DISTINCT id ) cnt2
           FROM t
          GROUP BY gb1, gb2 ) b
 WHERE a.gb1 = b.gb1
--일반 join문으로 하면 이렇게 하면 될 것 같은데 테이블에 두번 접근하게 되어 좀 비효율적이네요.
 
--rollup으로 한번만 접근하게 바꿔 봤습니다.
SELECT *
  FROM ( SELECT GB1
              , GB2
              , MAX( CNT2 ) OVER (PARTITION BY GB1) CNT1
              , CNT2
           FROM ( SELECT gb1, gb2, COUNT( DISTINCT id ) cnt2
                    FROM t
                  GROUP BY ROLLUP( gb1, gb2 ) 
                ) 
       )
 WHERE GB2 IS NOT NULL

그런데 예시 데이터 보면 광역시 회원수보다 대리점 회원수가 더 많을 수가 있나요?


by 마농 [2016.11.04 09:35:02]
SELECT gb1, gb2
     , cnt1
     , COUNT(*) cnt2
  FROM (SELECT gb1, gb2
             , COUNT(DISTINCT id) OVER(PARTITION BY gb1) cnt1
          FROM t
        )
 GROUP BY gb1, gb2, cnt1
;

 


by jkson [2016.11.04 10:02:47]

마농님 답변은 역시 쉽고 간단하네요. 쿼리 보다는 아이디어가 역시 중요하군요-0-


by 마농 [2016.11.04 10:07:36]
SELECT DISTINCT gb1, gb2
     , COUNT(DISTINCT id) OVER(PARTITION BY gb1) cnt1
     , COUNT(*) OVER(PARTITION BY gb1, gb2) cnt2
  FROM t
 ORDER BY gb1, gb2
;

 


by 신이만든짝퉁 [2016.11.04 10:50:10]

저랑 코드가 완전히 동일한 쿼리가 나왔네요;; ^^;

 

SELECT DISTINCT GB1, GB2, COUNT(DISTINCT ID) OVER(PARTITION BY GB1) CNT
     , COUNT(*) OVER(PARTITION BY GB1, GB2) CNT2
           FROM T
       ORDER BY GB1, GB2
;


 


by jkson [2016.11.04 10:58:33]

와 다들 아이디어가 좋으시네요~ 머리가 안돌아가면 역시 손발이 고생입니다ㅋ


by 달타냥 [2016.11.04 11:19:21]
조언에 깊이 감사드립니다
각 광역시에 속한 대리점 회원은 광역시 회원하고 같습니다
대리점을 통한 회원가입입니다
그런데 집계는 공역시 입장에서는 아래 대리점들 전체 회원을 유니크하게
집계내고 각 대리점은 자기네 화원을 유니크하게 집계내기때문에 서로 다릅니다
감사합니다
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입