id | strat_time | end_time |
aaaa | 2016-08-02 01:24:14 | 2016-08-02 01:25:59 |
aaaa | 2016-08-02 15:01:13 | 2016-08-02 17:16:44 |
aaaa | 2016-08-02 20:10:50 | 2016-08-03 01:34:17 |
bbbb | 2016-08-01 14:15:28 | 2016-08-01 15:39:03 |
bbbb | 2016-08-01 23:47:46 | 2016-08-02 00:22:26 |
cccc | 2016-08-01 15:11:33 | 2016-08-02 01:01:37 |
cccc | 2016-08-02 19:18:08 | 2016-08-03 00:12:32 |
dddd | 2016-08-02 14:11:37 | 2016-08-02 14:39:12 |
eeee | 2016-08-01 14:00:33 | 2016-08-01 19:26:20 |
WITH t AS ( select 'eeee' as id, '2016-08-01 14:00:33' as sdm, '2016-08-01 19:26:20' as edm union all select 'bbbb' as id, '2016-08-01 14:15:28' as sdm, '2016-08-01 15:39:04' as edm union all select 'cccc' as id, '2016-08-01 15:11:34' as sdm, '2016-08-02 01:01:37' as edm union all select 'bbbb' as id, '2016-08-01 23:47:47' as sdm, '2016-08-02 00:22:27' as edm union all select 'aaaa' as id, '2016-08-02 01:24:14' as sdm, '2016-08-02 01:25:59' as edm union all select 'dddd' as id, '2016-08-02 14:11:38' as sdm, '2016-08-02 14:39:12' as edm union all select 'aaaa' as id, '2016-08-02 15:01:13' as sdm, '2016-08-02 17:16:44' as edm union all select 'cccc' as id, '2016-08-02 19:18:09' as sdm, '2016-08-03 00:12:33' as edm union all select 'aaaa' as id, '2016-08-02 20:10:51' as sdm, '2016-08-03 01:34:17' as edm )
위와 같은 데이터가 있을때, 검색 조건을 2016-08-01에서 2016-08-02를 주었을때
결과값이
시간 | 이용자수 | 시작인원수 | 종료 인원수 |
14:00~14:59 | 3 | 3 | 1 |
15:00~15:59 | 4 | 2 | 1 |
16:00~16:59 | 3 | 0 | 0 |
17:00~17:59 | 3 | 0 | 1 |
18:00~18:59 | 2 | 0 | 0 |
19:00~19:59 | 3 | 1 | 1 |
20:00~20:59 | 3 | 1 | 0 |
21:00~21:59 | 3 | 0 | 0 |
22:00~22:59 | 3 | 0 | 0 |
23:00~23:59 | 4 | 1 | 0 |
24:00~24:59 | 4 | 0 | 2 |
25:00~25:59 | 3 | 1 | 3 |
이와 같이 나와야 합니다.
종료시간은 다음날 새벽 2시 까지 입니다.
이용자수는 그시간에 있는 사람들의 수이고, 시작인원수는 해당시간에 시작한 사람, 종료인원수는 해당시간에 종료한 사람 수 입니다.
고수님들의 답변 부탁드립니다.
잘 부탁 드립니다.
WITH T AS ( SELECT 'eeee' AS ID, TO_DATE('2016-08-01 14:00:33','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-01 19:26:20','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'bbbb' AS ID, TO_DATE('2016-08-01 14:15:28','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-01 15:39:04','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'cccc' AS ID, TO_DATE('2016-08-01 15:11:34','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-02 01:01:37','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'bbbb' AS ID, TO_DATE('2016-08-01 23:47:47','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-02 00:22:27','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'aaaa' AS ID, TO_DATE('2016-08-02 01:24:14','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-02 01:25:59','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'dddd' AS ID, TO_DATE('2016-08-02 14:11:38','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-02 14:39:12','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'aaaa' AS ID, TO_DATE('2016-08-02 15:01:13','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-02 17:16:44','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'cccc' AS ID, TO_DATE('2016-08-02 19:18:09','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-03 00:12:33','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL UNION ALL SELECT 'aaaa' AS ID, TO_DATE('2016-08-02 20:10:51','yyyy-mm-dd hh24:mi:ss') AS SDM, TO_DATE('2016-08-03 01:34:17','yyyy-mm-dd hh24:mi:ss') AS EDM FROM DUAL ) SELECT TO_CHAR(SDT,'hh24') SDT, TO_CHAR(EDT,'hh24') EDT ,SUM(CASE WHEN EDM >= SDT AND SDM < EDT THEN 1 ELSE 0 END) USERCNT ,SUM(CASE WHEN SDM >= SDT AND SDM < EDT THEN 1 ELSE 0 END) SCNT ,SUM(CASE WHEN EDM >= SDT AND EDM < EDT THEN 1 ELSE 0 END) ECNT FROM ( SELECT * FROM T WHERE EDM < TO_DATE(:EDM,'yyyy-mm-dd') + 26/24 AND SDM >= TO_DATE(:SDM,'yyyy-mm-dd') + 14/24 ) A , ( SELECT * FROM ( SELECT TO_DATE(:SDM,'yyyy-mm-dd') + 14/24 + (LEVEL - 1) /24 SDT , TO_DATE(:SDM,'yyyy-mm-dd') + 14/24 + (LEVEL) /24 EDT , LEVEL LV FROM DUAL WHERE TO_DATE(:SDM,'yyyy-mm-dd') + 14/24 + (LEVEL) /24 <= TO_DATE(:EDT,'yyyy-mm-dd') +26/24 CONNECT BY LEVEL < 1000 ) WHERE TO_CHAR(SDT,'hh24') BETWEEN '14' AND '23' OR TO_CHAR(SDT,'hh24') BETWEEN '00' AND '01' ) B WHERE EDM >= SDT AND SDM < EDT GROUP BY TO_CHAR(SDT,'hh24'), TO_CHAR(EDT,'hh24') ORDER BY DECODE(SDT,'00','24','01','25',SDT)
SQL SERVER 환경이 아니라.. 오라클에서 만들어봤습니다. 참고하시면 되겠네요.
WITH data_t AS ( SELECT 'aaaa' id, '2016-08-02 01:24:14' start_time, '2016-08-02 01:25:59' end_time UNION ALL SELECT 'aaaa', '2016-08-02 15:01:13', '2016-08-02 17:16:44' UNION ALL SELECT 'aaaa', '2016-08-02 20:10:50', '2016-08-03 01:34:17' UNION ALL SELECT 'bbbb', '2016-08-01 14:15:28', '2016-08-01 15:39:03' UNION ALL SELECT 'bbbb', '2016-08-01 23:47:46', '2016-08-02 00:22:26' UNION ALL SELECT 'cccc', '2016-08-01 15:11:33', '2016-08-02 01:01:37' UNION ALL SELECT 'cccc', '2016-08-02 19:18:08', '2016-08-03 00:12:32' UNION ALL SELECT 'dddd', '2016-08-02 14:11:37', '2016-08-02 14:39:12' UNION ALL SELECT 'eeee', '2016-08-01 14:00:33', '2016-08-01 19:26:20' ) , code_t AS ( -- 조회 기간 설정 -- SELECT CAST('02' AS VARCHAR(2)) gb , CAST('2016-08-01 02:00:00' AS DATETIME) stm , CAST('2016-08-01 02:59:59' AS DATETIME) etm UNION ALL SELECT CAST(RIGHT(CONCAT('0', gb+1), 2) AS VARCHAR(2)) gb , DATEADD(hour, 1, stm) , DATEADD(hour, 1, etm) FROM code_t WHERE gb <= 24 ) SELECT CONCAT(gb, ':00~', gb, ':59') gb , COUNT(DISTINCT id) cnt , COUNT(DISTINCT CASE WHEN start_time BETWEEN stm AND etm THEN id END) cnt1 , COUNT(DISTINCT CASE WHEN end_time BETWEEN stm AND etm THEN id END) cnt2 FROM code_t a INNER JOIN data_t b -- LEFT OUTER JOIN data_t b ON b.start_time <= a.etm AND b.end_time >= a.stm GROUP BY gb ;