시간 인터벌로 distinct를 다시 하기 1 8 1,940

by 지누기 [2014.10.28 18:23:21]


안녕하세요, 질문이 있어 이렇게 글을 남깁니다.

6개월 동안 특정 인물의 방문기록 중에서 한 사람이 방문한 횟수가 총 9번이고,

1월부터 6월까지의 기간 중, 1월에 2번, 4월에 3번, 6월에 4번 방문했다고 가정했을 때,

1월 1일부터 30일 간격으로 distinct해서, 총 3번 방문한 것으로 카운트를 내고자 합니다.

오라클 쿼리로 갖은 함수를 다 찾아보고 있는데 어떻게 풀어나가야 할 지 감이 오질 않습니다.

인터벌 별로 디스팅트 하는 것이 가능한지, 이와 연관있는 함수가 있는지 궁금합니다.

고수님 들의 의견이나 힌트 부탁드립니다. ㅠㅠ

 

by 비주류 [2014.10.29 00:01:57]

혹시 월별로 GROUP BY 하고 COUNT(COUNT(*)) 하는것과 다른가요?


by 지누기 [2014.10.29 09:15:31]

정확한 요구사항이 조회기간 중 첫번째 방문기록을 한 건으로 카운트 하고, 카운트된 로우의 방문일시

기준으로 30일 동안은 디스팅트해서 카운트 하지 않고, 30일 이후에 기록이 있으면 다시 카운트하고

이를 반복하는 형식입니다. 병원 쪽 검사에 관련된 요구사항이라 좀 복잡하네요.

쿼리로 안되면 30일 간격으로 데이터를 나눠서 각자 조회하고, 조회한 쿼리끼리 유니온해서 처리할까

싶기도 한데 그건 아닌 것 같아서 고민입니다. ㅠ_ㅠ


by 마농 [2014.10.29 09:24:31]

29일 간격으로 계속 방문한다면?

건수 계산이 어떻게 되나요?

계속해서 직전 방문과 29일 차이라서 1건만 카운트 하는 것인지?

아니면... 첫방문 이후 두번째는 29일 이라 카운트 안하고

세번째는 첫번째와 58일 차이이므로 새로 카운트

4번째 건너뛰고 5번째 카운트

이런 식으로 카운트 된 건만을 기준으로 비교 계산하는 건가요?


by 홍원표 [2014.10.29 09:36:37]
WITH TB_SAMPLE AS (
SELECT 'TEST' ID, '20140102' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140106' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140401' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140403' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140410' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140602' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140612' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140615' VDATE FROM DUAL UNION ALL
SELECT 'TEST' ID, '20140624' VDATE FROM DUAL 
)
SELECT SUBSTR(VDATE,1,6)
FROM TB_SAMPLE
WHERE ID ='TEST' 
AND VDATE BETWEEN '20140101' AND '20140630'
GROUP BY SUBSTR(VDATE,1,6)

 


by 지누기 [2014.10.29 09:44:02]

마농님께// 뒤에 말씀하신 방식이 맞습니다. 지정한 30일이라는 기간 간격 내에서는 무조건

한 건으로 처리하게 됩니다.

 

홍원표님께// 쿼리 만들어 주셔서 감사합니다. 월별 방문인 경우에는 이렇게 처리할 수 있을 것

같은데 제가 앞에서 설명을 잘못드렸었던거네요. 보내주신 쿼리 잘 참고하겠습니다.


by 마농 [2014.10.29 10:02:56]
WITH t AS
(
SELECT 1 id, '20140101' dt FROM dual
UNION ALL SELECT 1, '20140201' FROM dual
UNION ALL SELECT 1, '20140301' FROM dual
UNION ALL SELECT 1, '20140401' FROM dual
UNION ALL SELECT 1, '20140501' FROM dual
UNION ALL SELECT 1, '20140601' FROM dual
UNION ALL SELECT 1, '20140701' FROM dual
UNION ALL SELECT 2, '20140101' FROM dual
UNION ALL SELECT 2, '20140111' FROM dual
UNION ALL SELECT 2, '20140401' FROM dual
UNION ALL SELECT 2, '20140411' FROM dual
UNION ALL SELECT 2, '20140421' FROM dual
UNION ALL SELECT 2, '20140601' FROM dual
UNION ALL SELECT 2, '20140610' FROM dual
UNION ALL SELECT 2, '20140620' FROM dual
UNION ALL SELECT 2, '20140630' FROM dual
)
-- 10G MODEL --
SELECT COUNT(DISTINCT p_dt) cnt
  FROM (SELECT *
          FROM (SELECT ROW_NUMBER() OVER(ORDER BY dt) rn
                     , TO_DATE(dt, 'yyyymmdd') dt
                  FROM t
                 WHERE id = 2
                )
         MODEL
         DIMENSION BY (rn)
         MEASURES(dt, dt p_dt)
         RULES AUTOMATIC ORDER
         ( p_dt[rn > 1] = CASE WHEN dt[CV()] - p_dt[CV()-1] > 30
                               THEN dt[CV()]
                               ELSE p_dt[CV()-1]
                           END
         )
        )
;

 


by 마농 [2014.10.29 10:03:35]
WITH t AS
(
SELECT 1 id, '20140101' dt FROM dual
UNION ALL SELECT 1, '20140201' FROM dual
UNION ALL SELECT 1, '20140301' FROM dual
UNION ALL SELECT 1, '20140401' FROM dual
UNION ALL SELECT 1, '20140501' FROM dual
UNION ALL SELECT 1, '20140601' FROM dual
UNION ALL SELECT 1, '20140701' FROM dual
UNION ALL SELECT 2, '20140101' FROM dual
UNION ALL SELECT 2, '20140111' FROM dual
UNION ALL SELECT 2, '20140401' FROM dual
UNION ALL SELECT 2, '20140411' FROM dual
UNION ALL SELECT 2, '20140421' FROM dual
UNION ALL SELECT 2, '20140601' FROM dual
UNION ALL SELECT 2, '20140610' FROM dual
UNION ALL SELECT 2, '20140620' FROM dual
UNION ALL SELECT 2, '20140630' FROM dual
)
-- 11G Recursive SQL --
, t1 AS
(
SELECT ROW_NUMBER() OVER(ORDER BY dt) rn
     , dt
  FROM t
 WHERE id = 1
)
, t2(rn, dt, p_dt) AS
(
SELECT rn, dt
     , dt p_dt
  FROM t1
 WHERE rn = 1
 UNION ALL
SELECT a.rn, a.dt
     , CASE WHEN TO_DATE(a.dt, 'yyyymmdd') - TO_DATE(b.p_dt, 'yyyymmdd') > 30
            THEN a.dt ELSE b.p_dt END p_dt
  FROM t1 a
     , t2 b
 WHERE a.rn = b.rn + 1
)
SELECT COUNT(DISTINCT p_dt) cnt
  FROM t2
;

 


by 지누기 [2014.10.29 10:20:03]

마농님께// 쿼리 너무 감사드립니다. 참고하여 실력 열심히 쌓도록 하겠습니다.

댓글 달아주신 다른 분들께도 감사드립니다.
 

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