SQL 쿼리 질문 드립니다. 0 7 1,276

by 손님 [SQL Query] 쿼리 [2012.10.18 17:18:03]


SQL 초보라서 아무리 고민해도 답이 안나오네요.

ID        Startdate         Enddate       Class
-------------------------------------------------------------
1         20121001                               A
2         20121003                               B
3         20120920        20121002         B
4         20121001        20121005         C
5         20120901        20120930         A

이런 테이블이 있을 때

select class, count(*)  from table
where startdate <= '20121001'
and enddate > '20121001'
group by class

이렇게 쿼리를 하면 20121001일 현재 클래스별로 다니고 있는 사람들 수를 아래와 같이 구할 수
있을 텐데요. 

Class    Count(*)
-----------------------
A           1
B           1 
C           1


이걸 20121002, 20121003 식으로 해당 날짜 현재 다니고 있는 사람들 수를 구해서 10월 한달동안
각 날짜별로 다니는 사람들 수를 구해서 모두 합하게 하는 쿼리를 만들 수 있을까요? 
by 아발란체 [2012.10.18 18:00:09]
WITH T1 AS (
  SELECT 1 AS id, '20121001' AS startdate, '' AS enddate, 'A' AS cls FROM DUAL UNION ALL
  SELECT 2, '20121003', '', 'B' FROM DUAL UNION ALL
  SELECT 3, '20120920', '20121002', 'B' FROM DUAL UNION ALL
  SELECT 4, '20121001', '20121005', 'C' FROM DUAL UNION ALL
  SELECT 5, '20120901', '20120930','A' FROM DUAL 
), T2 AS (
  SELECT TO_DATE('2012-10-'||LPAD(LEVEL, 2, '0')) AS dday FROM DUAL CONNECT BY LEVEL <= 31
)
SELECT
  TO_CHAR(dday, 'YYYY-MM-DD') AS dday, COUNT(id) AS user_count
FROM
  T2
LEFT OUTER JOIN
  T1
ON
  dday >= startdate
  AND dday <= enddate
GROUP BY
  ROLLUP(dday)
ORDER BY
  dday nulls first

by 오케클릭 [2012.10.18 18:04:09]
-- 아래 쿼리중 '20120101' 은 원하는 달 01 날짜 입니다.
with t(id,startdate,enddate,class) as (
select '1','20121001',null,'A' from dual union all
select '2','20121003',null,'B' from dual union all
select '3','20120920','20121002','B' from dual union all
select '4','20121001','20121005','C' from dual union all
select '5','20120901','20120930','A' from dual
)
select b.dt, t.class, count(*) cnt from (
  select to_char(to_date('20121001','yyyymmdd')+(level-1),'yyyymmdd') dt from dual 
  connect by level <= to_number(to_char(last_day(to_date('20121001','yyyymmdd')),'dd'))
) b
left outer join t on t.startdate <= b.dt and nvl(enddate,'29991231') >= b.dt
group by ROLLUP((b.dt, t.class))
order by b.dt, t.class

by 아발란체 [2012.10.18 18:25:16]

악... 또 헛다리 짚었다~ !!!


by 오케클릭 [2012.10.18 18:46:38]

저도 마지막 부분이 좀 애매했는데... 맞는지 모르겠네요 질문자 의도를 추측할수밖에 없으니...


by 오케클릭 [2012.10.18 18:57:44]
-- 아래 쿼리중 '20120101' 은 원하는 달 01 날짜 입니다. 
-- 클래스별 데이터가 없으면 0 row 도 추가한 쿼리 입니다. 
with t(id,startdate,enddate,class) as ( 
select '1','20121001',null,'A' from dual union all
select '2','20121003',null,'B' from dual union all
select '3','20120920','20121002','B' from dual union all
select '4','20121001','20121005','C' from dual union all
select '5','20120901','20120930','A' from dual 
) 
select b.dt, t2.class, count(t.class) cnt from ( 
 select to_char(to_date('20121001','yyyymmdd')+(level-1),'yyyymmdd') dt from dual 
 connect by level <= to_number(to_char(last_day(to_date('20121001','yyyymmdd')),'dd')) 
) b 
inner join (select class from t group by class) t2 on 1=1 
left outer join t on t.startdate <= b.dt and nvl(enddate,'29991231') >= b.dt 
and t2.class = t.class 
group by ROLLUP((b.dt, t2.class)) 
order by b.dt, t2.class

by 마농 [2012.10.18 19:17:33]
질문이 잘 나가다가 끝에 모호해지네요.
원하시는 결과물을 보여주시는게 나을 듯.

by 손님 [2012.10.19 09:00:16]
오케클릭님 쿼리대로 하니까 되네요. 정말 감사드립니다. 
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입