오라클에서 mysql로 변환중인데 쿼리가 너무 복잡합니다.

조회수 2475회

오라클에서 mysql로 변환중입니다...

select
  days.mdate ,
  ifnull(login_cnt,0) as login_cnt ,
  ifnull(logout_cnt,0) as logout_cnt
  from ( select '2016-06-16' as mdate from ts_user where limit 1,1 ) days
  left join ( select substr(vl_date,0,10) as mdate ,
  sum(case when vl_login_yn = 'Y' then 1 else 0 end) login_cnt ,
  sum(case when vl_login_yn != 'Y' then 1 else 0 end) logout_cnt
  from
   ts_visit_log
   where substr(vl_date,0,10)
    between ? and ? 
    group by substr(vl_date,0,10) ) log
    on log.mdate = days.mdate
    order by days.mdate asc

대체 이게 무슨말인가요?

  • 쿼리가 무슨 의미인지를 말씀하시는건가요? 배경설명이 더 필요합니다. 정토드 2016.6.16 19:03

1 답변

  • 좋아요

    3

    싫어요
    채택 취소하기

    SQL의 구조는 다음과 같네요.

    select ... 
      from ( SUBQUERY1 ) mdate 
      left join ( SUBQUERY2 ) log 
      on log.mdate = days.mdate
        order by days.mdate asc
    
    1. ( SUBQUERY1 ) mdate 꼴은 SUBQUERY1의 결과를 mdate라는 이름의 테이블로 명명하겠다는 것입니다. 실제 테이블은 없고 임시로 존재하는 테이블이 됩니다.
    2. select ... from T1 left join T2 on CONDITION, 은 아시겠지만, T1(좌측)의 테이블을 기준으로 T2를 조인합니다. 만약 T1에 값이 있고 T2에 값이 없으면 T2에 해당하는 컬럼들은 NULL이 됩니다. 조인하는 기준값은 on 절에서 조건을 기술합니다.

    SQL문 설명

    1. ifnull(login_cnt,0) 만약 login_cnt가 null 이면 0 아니면 login_cnt 값을 사용합니다.
    2. XXX as login_cnt XXX의 결과(혹은 컬럼)을 컬럼 login_cnt로 부르겠다는 의미힙니다.

    SUBQUERY1

    select '2016-06-16' as mdate from ts_user where limit 1,1
    

    주: SUBQUERY1은 크게 의미가 있는 것 갖지는 않네요. mdate라는 컬럼하나 있는데 그 값이 2016-06-16 한개 row가 있도록 만들었네요.

    SQL문 설명

    1. limit 1,1 결과의 첫번째 레코드부터 1개로 제한한다는 의미입니다.

    SUBQUERY2

    select 
        substr(vl_date,0,10) as mdate ,
        sum(case when vl_login_yn = 'Y' then 1 else 0 end) login_cnt ,
        sum(case when vl_login_yn != 'Y' then 1 else 0 end) logout_cnt
    from
        ts_visit_log
    where substr(vl_date,0,10) between ? and ? 
    group by substr(vl_date,0,10) 
    

    주: SUBQUERY2가 위의 SQL이네요.

    SQL문 설명

    1. substr(xxxx,0,10)은 xxxx컬럼의 0번째부터 10글자를 추출한다는 의미입니다.
    2. case when vl_login_yn = 'Y' then 1 else 0 end 이것은 SQL의 선택문으로 vl_login_yn 컬럼의 값이 Y이면 1로 하고, 그렇지 않으면 0으로 합니다.
    3. XXX between ? and ? 이 문장에서 ?는 파라미터 바인딩을 해야 하는 위치를 의미합니다. 나중에 프로그램 코드에서 적용할 값을 제공(바인딩)하게 됩니다. SQL문의 뜻은 'XXX의 값이 첫번째 파라미터?와 두번째 파라미터 ? 사이에 있어야 한다'입니다.
    4. group by XXX 은 XXX의 값이 같은 것끼리 레코드를 묶습니다.
    5. sum(...) 함수는 4번의 group by 절에 의해 묶여진 레코드들에 대해서 연산하는 함수가 되겠습니다.

    정리

    특정기간안에 사용자 로그인횟수와 사용자 로그아웃 횟수를 계산한 임시테이블 log와 임시테이블 mdate를 조인해서, [날짜,로그인횟수,로그아웃횟수]를 계산하고, 날짜순으로 정렬한 것입니다.

    • 아이고 감사합니다 너무 많은 도움이 되었습니다^^ 김영광 2016.6.20 16:44

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)