날짜별 통계 질문드립니다 0 9 15,924

by 살라딘 [SQL Query] [2012.06.20 22:45:16]


안녕하세요, 

날자별 통계를 구하는 쿼리문을 작성하는데 잘 되지 않아 도움을 청합니다.

검색 시작일과 종료일을 WHERE 조건으로 아래와 같은 결과를 구하고 싶습니다.

예를 들어 06/20 일부터 07/01일 까지를 조건으로


날짜 전체 상품A(개)    상품B(개)    상품C(개)
0620   10       5            3               2
0621    4      3     1               0
0622   11      4     2             5
...
0701    5     2     5   10
전체              500    200       150     150



처음엔 야심찬(?) 계획으로 시작했는데, 벽에 부딪혔습니다,,,

그냥 날짜별 카운트는 뽑아낼수 있겠는데, 날짜별로 각 상품별 카운트와 날짜 전체 카운트까지....

열심히 삽질만 계속하고 있습니다;;;;

실제 데이터는 아래와 같은 형식입니다.


SEQ  ID PRODUCT DTIME(DATE)
1            111     상품A 2012/06/20
2 112     상품A 2012/06/20
3 113     상품B 2012/06/20
4 114     상품B 2012/06/20 
5 115     상품C 2012/06/21 
6         116     상품A 2012/06/21
7 117     상품A 2012/06/21
8 118     상품C 2012/06/22 
9 119     상품C 2012/06/22 
10 120     상품A 2012/06/22
  


제 실력이 부족해서인지, 도저히 쿼리가 나오지 않는데, 도움 부탁드립니다.

혹시 쿼리가 나올수 없는 구조인지, 가능하기는 한건지... 라는 생각이 자꾸 드네요;;;;;


by 마농 [2012.06.21 08:06:02]
SELECT NVL(TO_CHAR(dtime, 'yyyymmdd'), '전체') dt
     , COUNT(*) tot
     , COUNT(DECODE(product, '상품A', 1)) 상품A
     , COUNT(DECODE(product, '상품B', 1)) 상품B
     , COUNT(DECODE(product, '상품C', 1)) 상품C
  FROM t
 WHERE dtime >= TO_DATE('20120620', 'yyyymmdd')
   AND dtime <  TO_DATE('20120701', 'yyyymmdd') + 1
 GROUP BY ROLLUP(TO_CHAR(dtime, 'yyyymmdd'))
;

by 살라딘 [2012.06.22 00:27:05]
답변 감사합니다.

뭔가 어렵고, 복잡한 쿼리를 생각했었는데...

열줄 쿼리문을 못 짜서 헤멘걸 생각하면, 배움의 길이 멀다는 생각이 듭니다;;


위의 쿼리로 했더니, 결과가 잘 나옵니다.

그런데 카운트가 없는 날짜는 0으로 채워서 표시가 가능 할까요?

해당 날짜에 카운트가 하나도 없어도 0으로 채워서 검색 시작일부터 종료일까지

전부 ROW로 표시해주는게 가능할지 궁금합니다.

답변 주시면 감사하겠습니다.



by 마농 [2012.06.22 11:00:42]
SELECT NVL(a.dt, '전체') 날짜
     , NVL(SUM(b.tot), 0) tot
     , NVL(SUM(b.상품A), 0) 상품A
     , NVL(SUM(b.상품B), 0) 상품B
     , NVL(SUM(b.상품C), 0) 상품C
  FROM (SELECT TO_CHAR(TO_DATE('20120620', 'yyyymmdd') + LEVEL - 1, 'yyyymmdd') dt
          FROM dual
         CONNECT BY LEVEL <= TO_DATE('20120701', 'yyyymmdd')
                           - TO_DATE('20120620', 'yyyymmdd') + 1
        ) a
     , (SELECT TO_CHAR(dtime, 'yyyymmdd') dt
             , COUNT(*) tot
             , COUNT(DECODE(product, '상품A', 1)) 상품A
             , COUNT(DECODE(product, '상품B', 1)) 상품B
             , COUNT(DECODE(product, '상품C', 1)) 상품C
          FROM t
         WHERE dtime >= TO_DATE('20120620', 'yyyymmdd')
           AND dtime <  TO_DATE('20120701', 'yyyymmdd') + 1
         GROUP BY TO_CHAR(dtime, 'yyyymmdd')
        ) b
 WHERE a.dt = b.dt(+)
 GROUP BY ROLLUP(a.dt)
;

by mangoos [2017.05.29 04:53:03]

안녕하세요 

위 쿼리를  mysql 로 변경해서 알려주시면 정말 감사하겠습니다. 

초보인데 일주일 째 머리를 싸매고 있습니다. 


by 마농 [2017.05.29 08:05:48]

달력 테이블을 미리 만들어 두시고 사용하시면 편리합니다.
MySQL 달력 만들기 : http://www.gurubee.net/article/65315

SELECT IFNULL(a.dt, '전체') 날짜
     , IFNULL(SUM(b.tot), 0) tot
     , IFNULL(SUM(b.상품A), 0) 상품A
     , IFNULL(SUM(b.상품B), 0) 상품B
     , IFNULL(SUM(b.상품C), 0) 상품C
  FROM (SELECT dt
          FROM 달력테이블
         WHERE dt >= '20120620'
           AND dt <= '20120701'
        ) a
  LEFT OUTER JOIN
       (SELECT DATE_FORMAT(dtime, '%Y%m%d') dt
             , COUNT(*) tot
             , COUNT(CASE product WHEN '상품A' THEN 1 END) 상품A
             , COUNT(CASE product WHEN '상품B' THEN 1 END) 상품B
             , COUNT(CASE product WHEN '상품C' THEN 1 END) 상품C
          FROM t
         WHERE dtime >= CAST('20120620' AS DATE)
           AND dtime <  CAST('20120701' AS DATE) + INTERVAL 1 DAY
         GROUP BY DATE_FORMAT(dtime, '%Y%m%d')
        ) b
    ON a.dt = b.dt
 GROUP BY a.dt WITH ROLLUP
;

 


by apeach [2018.04.11 18:59:53]

제가 하려는 작업은 para_value 라는 컬럼과 그 컬럼의 카운트, 날짜를 조회하고 싶은 건데요. 

일단 데이터가 아래와 같다고 가정했을 경우..  ( reg_date 형식은 date 이며 년/월/일 까지만 나옵니다 )

para_value reg_date
test 18/03/06
test 18/03/06
test123 18/03/06
test 18/03/06
test123 18/03/06
apeach 18/03/06
test123 18/03/07
apeach 18/03/07
test 18/03/07

 

제가 위에 댓글을 참고하여 짠 쿼리는 아래와 같습니다... 



 SELECT
  NVL(TO_CHAR(REG_DATE, 'YYYY-MM-DD'), '전체') AS REG_DATE,
  COUNT(PARA_VALUE) AS CNT,                
  PARA_VALUE
FROM
EXT_IN                  
 WHERE  REG_DATE  between  TO_DATE('2018-03-06', 'YYYY-MM-DD') and TO_DATE('2018-03-06', 'YYYY-MM-DD')+1
 GROUP BY rollup(to_char(REG_DATE,'YYYY-MM-DD')),PARA_VALUE ;

 

제가 보고 싶은 데이터는... 

3월 6일로 조건을 주어 검색했을 경우 아래와 같이 결과가... 나왔으면 하는 바람입니다.... rollup이라는 조건?을 없애면... 실행이 안되더라구요..... 

제발 도와주세요 ㅠㅠㅠㅠㅠㅠ 

reg_date cnt para_value
2018-03-06 2 test123
2018-03-06 3 test
2018-03-06 1 apeach

 

아 그리고 where 절에 있는 between 조건은 저렇게 사용하면 되는게 맞을까요...? 

where 절에 있는 날짜 부분은 jsp에서 문자열로 넘어옵니다... 2018-03-06 이런 식으로요...  

아 그리고 날짜가 만약 2018-03-01~2018-03-31 이라면 날짜순으로 출력되었으면 좋겠는데.. 

그 조건은 어디에 주어야 하나요..? 


by apeach [2018.04.12 08:04:29]
SELECT
  TO_CHAR(REG_DATE, 'YYYY-MM-DD') AS REG_DATE,
  COUNT(PARA_VALUE) AS CNT,                
  PARA_VALUE
FROM
EXT_IN                  
 WHERE  REG_DATE  between  TO_DATE('2018-03-06', 'YYYY-MM-DD') and TO_DATE('2018-03-06', 'YYYY-MM-DD')+1
 GROUP BY (to_char(REG_DATE,'YYYY-MM-DD')),PARA_VALUE 
 order by REG_DATE desc

 

이 쿼리로 원하는 데이터가 나오는 것 까지는 해결 했습니다! !!!!~~~~~~~~

그런데 between은 저렇게 사용하는게 맞는건가요..? 

 


by 마농 [2018.04.12 09:25:13]

between 조건은 시작, 종료 조건 모두 등호(=)가 포함됩니다.
+ 1 을 사용하려면 등호가 빠져야 하고 등호가 포함되려면 + 0.99999 를 써야 합니다.
para_value 에 널이 없다면? 굳이 count(para_value) 할 이유 없습니다.
정렬기준은 중복되는 날짜만으로 하는 것 보다는 유니크한 조건을 추가해 주는 게 좋습니다.
질문은 댓글로 다는 것보다 새로 등록해 주시는게 좋을 듯 하네요.

SELECT TO_CHAR(reg_date, 'yyyy-mm-dd') AS reg_date
     , COUNT(*) AS cnt
     , para_value
  FROM ext_in
 WHERE reg_date BETWEEN TO_DATE('2018-03-06', 'yyyy-mm-dd')
                    AND TO_DATE('2018-03-06', 'yyyy-mm-dd') + 0.99999
 GROUP BY TO_CHAR(reg_date, 'yyyy-mm-dd'), para_value
 ORDER BY reg_date DESC, para_value
;

SELECT TO_CHAR(reg_date, 'yyyy-mm-dd') AS reg_date
     , COUNT(*) AS cnt
     , para_value
  FROM ext_in
 WHERE reg_date >= TO_DATE('2018-03-06', 'yyyy-mm-dd')
   AND reg_date <  TO_DATE('2018-03-06', 'yyyy-mm-dd') + 1
 GROUP BY TO_CHAR(reg_date, 'yyyy-mm-dd'), para_value
 ORDER BY reg_date DESC, para_value
;

 


by apeach [2018.04.12 12:13:50]

아 넵!!! 감사합니다! 다음번에는 새 글로 등록하도록 할게요! 

between이랑 부등호 쓰는거랑 차이를 이번에 명확하게 알게된 것 같습니다  감사합니다!!

두번째 만들어주신 쿼리로 적용하려구요..! ㅎㅎㅎㅎㅎ 

감사합니다! 정말 많은 도움이 되었습니다1

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입