본문 바로가기
Today I learned

2021 04 23 - SQL Booter COUNT의 비밀

by soheemon 2021. 4. 23.

COUNT의 비밀

  • COUNT는 NULL을 0으로 카운트 한다.
    집계에서 제외될것 같았는데 의외다. WHERE 조건식에서 NULL이 boolean값으로 판단되지 않는거와 비교하면 사뭇 다르다.

      select count(col1) cnt_col1
      ,count(col2) cnt_col2
      ,count(col3) cnt_col3
      from(
      select 'A' col1, NULL col2, 'C' col3 from dual union all
      select 'B' col1, NULL col2, NULL col3 from dual
      ) t1;

COUNT(*)과 COUNT(컬럼명)

  • COUNT(*) 는 로우 자체의 개수를 카운트 한다.

    select count(*) test1,
    count(col2)
    from(
    select 'A' col1, NULL col2, 'C' col3 from dual union all
    select 'B' col1, NULL col2, NULL col3 from dual
    ) t1;
  • 그래서 신기하게도 아래의 결과는 1이다.

    select count(*) from dual

count를 할때 중복을 제거하고 집계를 할 수 있다.

  • 전화번호로 가입한 고객중 중복을 제거하고 집계해보기.

    select count(distinct t1.phone)
    from(
    select '황소희' user_name, '010-1234-1234' phone from dual union all
    select '뽀삐' user_name, '010-1234-1234' phone from dual union all
    select '도토리' user_name, '010-423-6427' phone from dual union all
    select '도토리' user_name, '010-255-1234' phone from dual union all
    select '히히' user_name, '010-755-1234' phone from dual
    ) t1;

distinct의 기준을 여러개 줄 수도 있다.

  • 극단적인 예시긴 하지만, 핸드폰번호와 유저이름이 같으면 하나만 집계한다.

    예를들어, 아래의 결과는 4이다. 감재와 히히는 전화번호가 같지만, 이름이 달라서 다른 사람으로 판단하기 때문이다.

    select count(distinct t1.phone ||'-'|| user_name)
    from(
    select '황소희' user_name, '010-1234-1234' phone from dual union all
    select '황소희' user_name, '010-1234-1234' phone from dual union all
    select '황소희' user_name, '010-423-6427' phone from dual union all
    select '감재' user_name, '010-255-1234' phone from dual union all
    select '히히' user_name, '010-255-1234' phone from dual
    ) t1;
    
  • 인라인 뷰로도 동일한 효과를 낼 수 있다.
select count(\*)  
from (select distinct ord\_st, pay\_tp from t\_ord t1)

distinct의 사용 용도

  • 한번이라도 로그인 한 기록이 있는 사용자 수 등...
  • 인라인 뷰에서 부모테이블이랑 JOIN하는거 되게 헷갈렸는데 그냥 간단하게 생각하면 될것같다. 위치는 상관없고 그저 교집합을 가져오는것이다.
SELECT count(distinct 고객ID) from 로그인

SELECT COUNT(\*) FROM 고객 T1  
WHERE EXISTS( SELECT \* FROM 로그인 A WHERE A.고객ID = T1.고객ID)  

ROLLUP

  • ROLLUP은 GROUP BY 뒤에 ROLLUP이라고 적어서 사용한다.

    예를들어,

    GROUP BY ROLLUP(A,B,C,D) 하면 다음과 같은 데이터들이 집계된다.
  • GROUP BY된 A+B+C+D별 데이터
  • A+B+C별 소계 데이터
  • A+B별 소계 데이터
  • A별 소계 데이터
  • 전체 합계
ROLLUP 함수에서 나열하는 컬럼 순서는 중요하다.
GROUPING 함수는 특정 컬럼의 값이 소계인지 아닌지 구분해준다.

ROLLUP을 대체 할 수 있는 방법

UNION을 사용한다.
  • 기본적인 GROUP BY 데이터, 주문년월별 GROUP BY 데이터, GROUP BY 없는 전체 금액 합계를 별도로 만들어 UNION ALL한다.
    카테시안-조인으로 대신한다.
    CUBE
    WITH와 UNION ALL
    GROUPING SET

댓글