쿼리질문입니다 마농님 부탁드려요 ㅠㅠ => 정작 프로시져짜는수밖에없나요... 0 8 2,346

by 김용한 [SQL Query] [2015.05.21 17:17:04]


WITH T1 AS
(
select '5121500' stuno from dual union all
select '5121973' stuno from dual union all
select '4846456' stuno from dual union all
select '4992500' stuno from dual
)
select * from t1
;

WITH T AS
(
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5121500' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5121973' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5181999' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5182136' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5201322' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5243210' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5243406' stuno, 11 disp_ord from dual
)
select * from t
;
"수강신청"         "봉사활동" "결과1"      
day_gbn day_gbn_nm dtime stuno disp_ord   stuno   day_gbn day_gbn_nm dtime nm_list
2 1A(08:00) 5121500 11   5121500   2 1A(08:00) 5121500, 5121973
2 1A(08:00) 5121973 11   5121973   "결과2"      
2 1A(08:00) 5181999 11   4846456   day_gbn day_gbn_nm dtime nm_list
2 1A(08:00) 5182136 11   4992500   2 1A(08:00) 4846456, 4992500
2 1A(08:00) 5201322 11              
2 1A(08:00) 5243210 11              
2 1A(08:00) 5243406 11              

"수강신청" 테이블이랑 "봉사활동" 테이블을 이용하여서 결과 1은 낼수있엇는데

결과2를 내고싶습니다 즉

"봉사활동" 테이블의 stuno 에 해당하는 학번이 "수강신청" 테이블의 day_gbn, dtime 에 따른

학번의 결과값 즉 5121500, 5212973 의 나머지값인 "봉사활동"의 4846456, 4992500 의 값을 결과 2처럼 보여주고싶습니다

쉽지가않네요 ...

by swlee710 [2015.05.21 17:43:31]

wITH T1 AS
(
select '5121500' stuno from dual union all
select '5121973' stuno from dual union all
select '4846456' stuno from dual union all
select '4992500' stuno from dual
),
t as(
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5121500' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5121973' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5181999' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5182136' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5201322' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5243210' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5243406' stuno, 11 disp_ord from dual
)
select day_gbn,day_gbn_nm,dtime,listagg(stuno,',') within group(order by stuno) nm_list 
from (
select distinct aa.stuno,aa.day_gbn,aa.day_gbn_nm,aa.dtime,aa.disp_ord, nvl2(cc.stuno,1,2) gb
from (
select  a.stuno,day_gbn,day_gbn_nm,dtime,disp_ord
from t1 a, t b) aa, t1 bb, t cc
where aa.stuno = bb.stuno
  and aa.stuno = cc.stuno (+))
group by gb,day_gbn,day_gbn_nm,dtime,disp_ord
;


by 김용한 [2015.05.21 17:53:50]

기준테이블을 봉사활동으로 하셧네요...

제가원하는것은 기준테이블이 수강신청테이블이에요 ^^

그리고 수강신청테이블은 월,화,수,목,금,토 까지있구요

각요일(6)마다 25개의 수강시간개수가 곱해집니다 그래서 150개입니다 그중에 한개를

샘플로 올린거구요 ㅠㅠ 

 


by jkson [2015.05.21 18:02:42]

설명이 부족하네요. 결과1을 도출해내신 쿼리도 올려주시면 결과2를 만드는 데 도움이 되지 않을까요?


by 김용한 [2015.05.21 18:06:12]

아래의 쿼리가 결과1을도출해내는 쿼리입니다 보시다시피 쉬워요 ^^

근데 반대의 결과 학생집합을 가져오려니 힘들더라구요 ㅠㅠ

WITH T1 AS
(
select '5121500' stuno from dual union all
select '5121973' stuno from dual union all
select '4846456' stuno from dual union all
select '4992500' stuno from dual
)
,
T AS
(
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5121500' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5121973' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5181999' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5182136' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5201322' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5243210' stuno, 11 disp_ord from dual union all
select '2' day_gbn, '월' day_gbn_nm, '1A(08:00)' dtime, '5243406' stuno, 11 disp_ord from dual
)
select t.day_gbn
     , t.DAY_GBN_NM
     , t.dtime
     , t.disp_ord
     , listagg(t1.stuno,',') within group(order by t.day_gbn,t.disp_ord ) as nm_list
     , count(t1.stuno)
  from t, t1
 where t.stuno = t1.stuno(+)
 group by t.day_gbn,t.day_gbn_nm, t.dtime, t.disp_ord
 order by t.day_gbn, t.disp_ord
;


by 마농 [2015.05.22 09:31:02]
SELECT t.day_gbn
     , t.day_gbn_nm
     , t.dtime
     , t.disp_ord
     , LISTAGG(t1.stuno, ',') WITHIN GROUP(ORDER BY t.day_gbn, t.disp_ord) AS nm_list
     , COUNT(t1.stuno) AS cnt
  FROM t1
  LEFT OUTER JOIN t
  PARTITION BY (t.day_gbn, t.day_gbn_nm, t.dtime, t.disp_ord)
    ON t.stuno = t1.stuno
 WHERE t.stuno IS NULL
 GROUP by t.day_gbn, t.day_gbn_nm, t.dtime, t.disp_ord
 ORDER by t.day_gbn, t.disp_ord
;

 


by 김용한 [2015.05.22 10:06:30]

감사합니다 왜저렇게돼는지 이해가안돼네요 설명좀 부탁드립니다...


by 마농 [2015.05.22 10:59:41]

아우터 조인의 기준이 무었인지 명확하게 판단해야 하는 문제인데요.
언듯 보면 t1 을 기준으로 t 에 없는 것을 나와야 하므로 t1 이 기준인 듯 보이지만
t 에 없는 것을 조회하면서 t 의 값이 조회되어야만 하는 모순에 빠지게 됩니다.
결국 기준은 t1 이 아니라는 거구요.
기준은 t1 + t 의 크로스조인 조합입니다.
t1의 코드와 t의 요일이 함께 조합된 결과 집합이 기준이 되어야 합니다.

SELECT x.day_gbn
     , x.day_gbn_nm
     , x.dtime
     , x.disp_ord
     , LISTAGG(x.stuno, ',') WITHIN GROUP(ORDER BY x.day_gbn, x.disp_ord) AS nm_list
     , COUNT(x.stuno) AS cnt
  FROM (SELECT day_gbn, day_gbn_nm, dtime, disp_ord
             , stuno
          FROM t1 a
             , (SELECT DISTINCT day_gbn, day_gbn_nm, dtime, disp_ord FROM t) b
        ) x
     , t y
 WHERE x.day_gbn    = y.day_gbn   (+)
   AND x.day_gbn_nm = y.day_gbn_nm(+)
   AND x.dtime      = y.dtime     (+)
   AND x.disp_ord   = y.disp_ord  (+)
   AND x.stuno      = y.stuno     (+)
   AND y.stuno IS NULL
 GROUP BY x.day_gbn, x.day_gbn_nm, x.dtime, x.disp_ord
 ORDER BY x.day_gbn, x.disp_ord
;


위 쿼리의 과정을 살펴보면
1. 기준집합을 얻기 위해 t 를 Distinct 하고 t1 과 Cross Join 합니다.
2. 그리고 그결과를 기준으로 t 를 아우터 조인합니다.
3. 아우터 조인 결과가 없는(y.stuno IS NULL) 것만 걸러내고
4. 그룹바이로 집계하여 마무리합니다.
하지만 t 테이블을 2번이나 읽고 있습니다.
PARTITION OUTER JOIN 을 이용하면 1번만 읽고도 이 모순을 해결할 수 있습니다.
t1 을 기준으로 해서 t 를 아우터 조인 거는데, t 의 그룹별로 아우터 조인을 하는 구문입니다.


by 김용한 [2015.05.22 11:18:47]

그동안 어렵게 느낀 쿼리였는데 설명 무지감사하네요 많이배우고갑니다...

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