by 마농 CROSS JOIN LEFT OUTER JOIN ORA-01417 ORA-01719 퀴즈 [2012.04.17]
S_ID | S_NM |
---|---|
001 | 기민용 |
002 | 이현석 |
003 | 김정식 |
004 | 강정식 |
C_ID | C_NM |
---|---|
001 | Database |
002 | Java |
S_ID | C_ID | CHASU |
---|---|---|
001 | 001 | 1 |
001 | 001 | 3 |
001 | 002 | 2 |
002 | 001 | 1 |
002 | 001 | 2 |
002 | 001 | 3 |
003 | 002 | 1 |
003 | 002 | 2 |
004 | 001 | 1 |
ID | 성명 | 스터디 | 1차 | 2차 | 3차 | 참여횟수 |
---|---|---|---|---|---|---|
001 | 기민용 | Database | ○ | ○ | 2 | |
Java | ○ | 1 | ||||
002 | 이현석 | Database | ○ | ○ | ○ | 3 |
Java | 0 | |||||
003 | 김정식 | Database | 0 | |||
Java | ○ | ○ | 2 | |||
004 | 강정식 | Database | ○ | 1 | ||
Java | 0 |
WITH student AS ( SELECT '001' s_id, '기민용' s_nm FROM dual UNION ALL SELECT '002', '이현석' FROM dual UNION ALL SELECT '003', '김정식' FROM dual UNION ALL SELECT '004', '강정식' FROM dual ) , course AS ( SELECT '001' c_id, 'Database' c_nm FROM dual UNION ALL SELECT '002', 'Java' FROM dual ) , study AS ( SELECT '001' s_id, '001' c_id, 1 chasu FROM dual UNION ALL SELECT '001', '001', 3 FROM dual UNION ALL SELECT '001', '002', 2 FROM dual UNION ALL SELECT '002', '001', 1 FROM dual UNION ALL SELECT '002', '001', 2 FROM dual UNION ALL SELECT '002', '001', 3 FROM dual UNION ALL SELECT '003', '002', 1 FROM dual UNION ALL SELECT '003', '002', 2 FROM dual UNION ALL SELECT '004', '001', 1 FROM dual ) -- 이곳에 들어갈 쿼리를 작성해 주세요.
SELECT CASE WHEN b.c_id = '001' THEN a.s_id END AS "ID" , CASE WHEN b.c_id = '001' THEN a.s_nm END AS "성명" , b.c_nm AS "스터디" , MIN(CASE WHEN c.chasu = 1 THEN '○' END) AS "1차" , MIN(CASE WHEN c.chasu = 2 THEN '○' END) AS "2차" , MIN(CASE WHEN c.chasu = 3 THEN '○' END) AS "3차" , COUNT(c.s_id) AS "참여횟수" FROM student a CROSS JOIN course b LEFT OUTER JOIN study c ON a.s_id = c.s_id AND b.c_id = c.c_id GROUP BY a.s_id, a.s_nm, b.c_id, b.c_nm ORDER BY a.s_id, b.c_id;
이 문제는 3개의 테이블을 조인하여 결과를 도출하는 문제입니다.
위의 문제에 제시된 여러 단서 조항들을 한꺼번에 모두 적용하지 않고 한단계, 한단계 차근차근 접근하면서 문제를 해결해 나가는 방법으로 설명하겠습니다.
SELECT a.s_id, a.s_nm, b.c_id, b.c_nm, c.chasu FROM student a, course b, study c WHERE a.s_id = c.s_id AND b.c_id = c.c_id ORDER BY a.s_id, b.c_id, c.chasu;
S_ID | S_NM | C_ID | C_NM | CHASU |
---|---|---|---|---|
001 | 기민용 | 001 | Database | 1 |
001 | 기민용 | 001 | Database | 3 |
001 | 기민용 | 002 | Java | 2 |
002 | 이현석 | 001 | Database | 1 |
002 | 이현석 | 001 | Database | 2 |
002 | 이현석 | 001 | Database | 3 |
003 | 김정식 | 002 | Java | 1 |
003 | 김정식 | 002 | Java | 2 |
004 | 강정식 | 001 | Database | 1 |
조인을 한 후 s_id, c_id 로 그룹핑하여 차수를 옆으로 나열하는 단계입니다.
SELECT a.s_id, a.s_nm, b.c_id, b.c_nm , MIN(CASE WHEN c.chasu = 1 THEN '○' END) AS "1차" , MIN(CASE WHEN c.chasu = 2 THEN '○' END) AS "2차" , MIN(CASE WHEN c.chasu = 3 THEN '○' END) AS "3차" , COUNT(c.s_id) AS "참여횟수" FROM student a , course b , study c WHERE a.s_id = c.s_id AND b.c_id = c.c_id GROUP BY a.s_id, a.s_nm, b.c_id, b.c_nm ORDER BY a.s_id, b.c_id;
원하던 결과와 매우 유사한 형태의 결과가 나왔습니다.
S_ID | S_NM | C_ID | C_NM | 1차 | 2차 | 3차 | 참여횟수 |
---|---|---|---|---|---|---|---|
001 | 기민용 | 001 | Database | ○ | ○ | 2 | |
001 | 기민용 | 002 | Java | ○ | 1 | ||
002 | 이현석 | 001 | Database | ○ | ○ | ○ | 3 |
003 | 김정식 | 002 | Java | ○ | ○ | 2 | |
004 | 강정식 | 001 | Database | ○ | 1 |
자, 이제 없는 스터디 과목도 나오도록 해야겠습니다. 아우터 조인을 이용하면 되겠죠. 다음과 같이 study 테이블에 아우터조인을 걸어 쿼리를 실행해 보겠습니다.
SELECT a.s_id, a.s_nm, b.c_id, b.c_nm , MIN(CASE WHEN c.chasu = 1 THEN '○' END) AS "1차" , MIN(CASE WHEN c.chasu = 2 THEN '○' END) AS "2차" , MIN(CASE WHEN c.chasu = 3 THEN '○' END) AS "3차" , COUNT(c.s_id) AS "참여횟수" FROM student a , course b , study c WHERE a.s_id = c.s_id(+) AND b.c_id = c.c_id(+) GROUP BY a.s_id, a.s_nm, b.c_id, b.c_nm ORDER BY a.s_id, b.c_id;
ORA-01417 : 하나의 테이블은 하나의 다른 테이블과 포괄 조인할 수 있습니다
예기치 못한 에러가 발생했습니다. c를 a, b 두개 집합과 아우터조인을 하려고 해서 발생한 에러입니다. 이를 해결하기 위해서는 a, b를 하나의 집합으로 만들어야 합니다.
SELECT a.s_id, a.s_nm, a.c_id, a.c_nm , MIN(CASE WHEN c.chasu = 1 THEN '○' END) AS "1차" , MIN(CASE WHEN c.chasu = 2 THEN '○' END) AS "2차" , MIN(CASE WHEN c.chasu = 3 THEN '○' END) AS "3차" , COUNT(c.s_id) AS "참여횟수" FROM (SELECT a.s_id, a.s_nm, b.c_id, b.c_nm FROM student a, course b ) a , study c WHERE a.s_id = c.s_id(+) AND a.c_id = c.c_id(+) GROUP BY a.s_id, a.s_nm, a.c_id, a.c_nm ORDER BY a.s_id, a.c_id
S_ID | S_NM | C_ID | C_NM | 1차 | 2차 | 3차 | 참여횟수 |
---|---|---|---|---|---|---|---|
001 | 기민용 | 001 | Database | ○ | ○ | 2 | |
001 | 기민용 | 002 | Java | ○ | 1 | ||
002 | 이현석 | 001 | Database | ○ | ○ | ○ | 3 |
002 | 이현석 | 002 | Java | 0 | |||
003 | 김정식 | 001 | Database | 0 | |||
003 | 김정식 | 002 | Java | ○ | ○ | 2 | |
004 | 강정식 | 001 | Database | ○ | 1 | ||
004 | 강정식 | 002 | Java | 0 |
a 와 b를 조인하려고 했는데 원래부터 둘 사이엔 아무런 관계가 없었네요. 조인조건을 줄 수가 없습니다. 조건 없이 조인을 하게 되는 것입니다.
위 결과 중 노란색으로 표시한 부분이 바로 인라인뷰의 결과입니다. 우리가 원하던 바로 그 결과가 나왔습니다.
이는 c_id 값 두개중 한개만 선택적으로 출력되도록 Case문을 사용하면 됩니다.
SELECT CASE WHEN a.c_id = '001' THEN a.s_id END s_id , CASE WHEN a.c_id = '001' THEN a.s_nm END s_nm
이제 거의 모든 조건을 만족하게 되었습니다. 단, 한가지 조건을 만족하지 못하네요. 바로, 서브 쿼리 사용 안하기 조건입니다.
아우터조인 시 에러를 해결하기 위해 부득이하게 서브쿼리를 사용했습니다. 만약, 서브쿼리를 사용 안한다면 아우터조인 에러를 해결할 수 없습니다.
오라클에서 사용하는 를 이용한 (+) 아우터조인에는 몇가지 제약사항이 있습니다.
위 제약사항은 ANSI SQL 의 Outer Join을 이용하면 해결이 가능합니다.
SELECT CASE WHEN b.c_id = '001' THEN a.s_id END AS "ID" , CASE WHEN b.c_id = '001' THEN a.s_nm END AS "성명" , b.c_nm AS "스터디" , MIN(CASE WHEN c.chasu = 1 THEN '○' END) AS "1차" , MIN(CASE WHEN c.chasu = 2 THEN '○' END) AS "2차" , MIN(CASE WHEN c.chasu = 3 THEN '○' END) AS "3차" , COUNT(c.s_id) AS "참여횟수" FROM student a CROSS JOIN course b LEFT OUTER JOIN study c ON a.s_id = c.s_id AND b.c_id = c.c_id GROUP BY a.s_id, a.s_nm, b.c_id, b.c_nm ORDER BY a.s_id, b.c_id;
드디어 정답을 완성했습니다.
오라클에서 사용하던 Sql문법과는 많이 생소한 구문입니다.
이번 퀴즈의 정답은 매우 간단하지만 결과 도출과정은 그리 만만하지 않습니다.
기본적으로 테이블간의 관계를 알고 조인에 대한 기본개념을 알고 있어야 하며 그룹바이를 이용하여 행을 열로 바꾸어 표시하는 방법 아우터 조인의 개념과 제약사항 ANSI SQL의 사용법까지 알아야 합니다.
이번 퀴즈를 통해 이 모든 것들을 자기 것으로 만들 수 있는 계기가 되었으면 합니다.
- 강좌 URL : http://www.gurubee.net/lecture/2190
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.
WITH student AS ( SELECT '001' s_id, '기민용' s_nm FROM dual UNION ALL SELECT '002', '이현석' FROM dual UNION ALL SELECT '003', '김정식' FROM dual UNION ALL SELECT '004', '강정식' FROM dual ) , course AS ( SELECT '001' c_id, 'Database' c_nm FROM dual UNION ALL SELECT '002', 'Java' FROM dual ) , study AS ( SELECT '001' s_id, '001' c_id, 1 chasu FROM dual UNION ALL SELECT '001', '001', 3 FROM dual UNION ALL SELECT '001', '002', 2 FROM dual UNION ALL SELECT '002', '001', 1 FROM dual UNION ALL SELECT '002', '001', 2 FROM dual UNION ALL SELECT '002', '001', 3 FROM dual UNION ALL SELECT '003', '002', 1 FROM dual UNION ALL SELECT '003', '002', 2 FROM dual UNION ALL SELECT '004', '001', 1 FROM dual ) select CASE WHEN c.c_id = '001' THEN s.s_id END id , CASE WHEN c.c_id = '001' THEN s.s_nm END 이름 , c.c_nm 스터디, CASE when st.chasu = 1 then 'O' END "1차", CASE when st.chasu = 2 then 'O' END "2차", CASE when st.chasu = 3 then 'O' END "3차", count(st.s_id) 참여회수 from student s, course c, study st where s.s_id = st.s_id and c.c_id=st.c_id group by c.c_id, st.chasu, s.s_id, s.s_nm, c.c_nm order by s.s_id
with문을 사용하지 않고 피벗을 사용해봤습니다. 피벗으로 짜도 서브쿼리가 들어가네요ㅠ
select s_id, s_nm, c_nm,
(case when "'1'" = 1 then 'O' end) as "1차"
, (case when "'2'" = 1 then 'O' end) as "2차"
, (case when "'3'" = 1 then 'O' end) as "3차"
, total as "참여횟수"
from
(
select stent.s_id, stent.s_nm, cors.c_nm, stdy.chasu,
(select count(s_id) from tstudy where s_id =stent.s_id and c_id = cors.c_id and chasu = stdy.chasu) as count1,
(select count(s_id) from tstudy where s_id =stent.s_id and c_id = cors.c_id ) as total
from tstudent stent, tcourse cors, tstudy stdy
group by stdy.chasu,stent.s_id, stent.s_nm, cors.c_nm, cors.c_id
)
pivot(
sum(count1)
for chasu in ('1' , '2', '3')
)
order by s_id;
SELECT S_ID, S_NM, C_NM, MAX(CASE WHEN CHASU='1' AND LV=1 THEN 'O' ELSE NULL END) AS CHASU1, MAX(CASE WHEN CHASU='2' AND LV=2 THEN 'O' ELSE NULL END) AS CHASU2, MAX(CASE WHEN CHASU='3' AND LV=3 THEN 'O' ELSE NULL END) AS CHASU3 , MAX(CASE WHEN CHASU='1' AND LV=1 THEN 1 ELSE 0 END) + MAX(CASE WHEN CHASU='2' AND LV=2 THEN 1 ELSE 0 END) + MAX(CASE WHEN CHASU='3' AND LV=3 THEN 1 ELSE 0 END) AS SUM FROM (WITH student AS ( SELECT '001' s_id, '기민용' s_nm FROM dual UNION ALL SELECT '002', '이현석' FROM dual UNION ALL SELECT '003', '김정식' FROM dual UNION ALL SELECT '004', '강정식' FROM dual ) , course AS ( SELECT '001' c_id, 'Database' c_nm FROM dual UNION ALL SELECT '002', 'Java' FROM dual ) , study AS ( SELECT '001' s_id, '001' c_id, 1 chasu FROM dual UNION ALL SELECT '001', '001', 3 FROM dual UNION ALL SELECT '001', '002', 2 FROM dual UNION ALL SELECT '002', '001', 1 FROM dual UNION ALL SELECT '002', '001', 2 FROM dual UNION ALL SELECT '002', '001', 3 FROM dual UNION ALL SELECT '003', '002', 1 FROM dual UNION ALL SELECT '003', '002', 2 FROM dual UNION ALL SELECT '004', '001', 1 FROM dual ) select a.s_id,s_nm, b.c_nm, c.chasu from student a, course b, study c where a.s_id = c.s_id and b.c_id = c.c_id ) A , (SELECT LEVEL LV FROM DUAL CONNECT BY LEVEL <=3) B GROUP BY S_ID, S_NM, C_NM ORDER BY S_ID, C_NM
답안을 안보고 짠건데.. 답을보니 많이 배운거같습니다.
제가짠거는 java나 database과목이 신청건이 0인건 나오지 않아서 left조인을 과목기준으로 걸어보고 그랬는데..안되더라구요 cross 조인을 이럴때 쓰는지 확실히 알고가요
행을 열로 바꿀때 level을 조인걸어서 자주사용했는데, 위 문제같은경우는 chasu자체로 level역할을해서 필요가 없었네요 ^^;
case문으로 한번만 나타나는것도 직접짤땐 생각이 안나다가 답을 보니 아.. 가 절로나오네요 ㅎㅎ;;
SELECT DECODE(a.s_id,LAG(a.s_id) OVER(ORDER BY a.s_id),'',a.s_id) ID ,DECODE(a.s_nm,LAG(a.s_nm) OVER(ORDER BY a.s_id),'',a.s_nm) "성명" ,b.c_nm "스터디" ,MIN(DECODE(c.chasu,1,'O')) "1차" ,MIN(DECODE(c.chasu,2,'O'))"2차" ,MIN(DECODE(c.chasu,3,'O')) "3차" ,COUNT(c.chasu) "참여횟수" FROM student a, course b, study c WHERE a.s_id = c.s_id(+) AND b.c_id = c.c_id(+) GROUP BY A.S_ID,A.S_NM,B.C_ID,B.C_NM ORDER BY A.S_ID
이렇게 짯는데 조금 달라영... 이래도대나염?
SELECT MAX(DECODE(C.C_ID, '001', S.S_ID, NULL)) AS "ID", MAX(DECODE(C.C_ID, '001', S.S_NM, NULL)) AS "성명", C.C_NM AS "스터디", MAX(DECODE(ST.CHASU, 1, '○', NULL)) AS "1차", MAX(DECODE(ST.CHASU, 2, '○', NULL)) AS "2차", MAX(DECODE(ST.CHASU, 3, '○', NULL)) AS "3차", COUNT(ST.S_ID) AS "참여횟수" FROM STUDENT S CROSS JOIN COURSE C LEFT OUTER JOIN STUDY ST ON S.S_ID = ST.S_ID AND C.C_ID = ST.C_ID GROUP BY S.S_ID, S.S_NM, C.C_ID, C.C_NM ORDER BY S.S_ID, C.C_ID
SELECT DECODE(A.S_ID,LAG(A.S_ID) OVER(ORDER BY A.S_ID),NULL,A.S_ID) ID ,DECODE(A.S_NM,LAG(A.S_NM) OVER(ORDER BY A.S_ID),NULL,A.S_NM) NAME ,B.C_NM ,MIN(DECODE(CHASU,1,0)) "1차" ,MIN(DECODE(CHASU,2,0)) "2차" ,MIN(DECODE(CHASU,3,0)) "3차" ,COUNT(CHASU) CNT FROM STUDENT A RIGHT JOIN COURSE B PARTITION BY (C_NM) ON A.S_NM != B.C_NM LEFT JOIN STUDY C ON A.S_ID = C.S_ID AND B.C_ID = C.C_ID GROUP BY A.S_ID,A.S_NM,B.C_ID,B.C_NM ORDER BY A.S_ID,A.S_NM,B.C_ID
여기 문제들 푼지 3개월 후 다시 풀어 보려구요!
3개월 전이랑은 다른쿼리를 짯네여 ㅋㅋ
다시풀면서 제가 얼마나 늘었는지 테스트해볼게여
WITH student AS
(
SELECT '001' s_id, '기민용' s_nm FROM dual
UNION ALL SELECT '002', '이현석' FROM dual
UNION ALL SELECT '003', '김정식' FROM dual
UNION ALL SELECT '004', '강정식' FROM dual
)
, course AS
(
SELECT '001' c_id, 'Database' c_nm FROM dual
UNION ALL SELECT '002', 'Java' FROM dual
)
, study AS
(
SELECT '001' s_id, '001' c_id, 1 chasu FROM dual
UNION ALL SELECT '001', '001', 3 FROM dual
UNION ALL SELECT '001', '002', 2 FROM dual
UNION ALL SELECT '002', '001', 1 FROM dual
UNION ALL SELECT '002', '001', 2 FROM dual
UNION ALL SELECT '002', '001', 3 FROM dual
UNION ALL SELECT '003', '002', 1 FROM dual
UNION ALL SELECT '003', '002', 2 FROM dual
UNION ALL SELECT '004', '001', 1 FROM dual
)
select b.s_id as "ID", MAX(b.s_nm) 성명 , c.c_nm as "스터디"
,MIN(decode (a.chasu, '1', decode(a.c_id, c.c_id,'O',''),'' )) AS "1차"
,MIN(decode (a.chasu, '2', decode(a.c_id, c.c_id,'O',''),'' )) AS "2차"
,MIN(decode (a.chasu, '3', decode(a.c_id, c.c_id,'O',''),'' )) AS "3차"
,count(decode(a.c_id, c.c_id,1,null)) as "참여횟수"
from study a , student b , course c
where a.s_id = b.s_id
GROUP BY b.S_ID , C.C_NM
ORDER BY b.s_id, C.C_NM
decode를 사용해서 만들어 봤어요. 이거 정답 맞나요 ?
WITH student AS
(
SELECT '001' s_id, '기민용' s_nm FROM dual
UNION ALL SELECT '002', '이현석' FROM dual
UNION ALL SELECT '003', '김정식' FROM dual
UNION ALL SELECT '004', '강정식' FROM dual
)
, course AS
(
SELECT '001' c_id, 'Database' c_nm FROM dual
UNION ALL SELECT '002', 'Java' FROM dual
)
, study AS
(
SELECT '001' s_id, '001' c_id, 1 chasu FROM dual
UNION ALL SELECT '001', '001', 3 FROM dual
UNION ALL SELECT '001', '002', 2 FROM dual
UNION ALL SELECT '002', '001', 1 FROM dual
UNION ALL SELECT '002', '001', 2 FROM dual
UNION ALL SELECT '002', '001', 3 FROM dual
UNION ALL SELECT '003', '002', 1 FROM dual
UNION ALL SELECT '003', '002', 2 FROM dual
UNION ALL SELECT '004', '001', 1 FROM dual
)
select case when b.c_id = '001' then a.s_id end as "ID",
case when b.c_id = '001' then min(a.s_nm) end as "성명",
min(b.c_id) as "성별",
min(b.c_nm) as "스터디",
min((case when c.chasu = 1 then 'o' end)) as "1차",
min((case when c.chasu = 2 then 'o' end)) as "2차",
min((case when c.chasu = 3 then 'o' end)) as "3차",
count(c.chasu)
from student a , course b,study c
where a.s_id = c.s_id (+)
and b.c_id = c.c_id (+)
group by a.s_id, b.c_id
order by a.s_id, b.c_id
;
어렵습니다 열심히 공부하겠습니다.
WITH student AS ( SELECT '001' s_id, '기민용' s_nm FROM dual UNION ALL SELECT '002', '이현석' FROM dual UNION ALL SELECT '003', '김정식' FROM dual UNION ALL SELECT '004', '강정식' FROM dual ) , course AS ( SELECT '001' c_id, 'Database' c_nm FROM dual UNION ALL SELECT '002', 'Java' FROM dual ) , study AS ( SELECT '001' s_id, '001' c_id, 1 chasu FROM dual UNION ALL SELECT '001', '001', 3 FROM dual UNION ALL SELECT '001', '002', 2 FROM dual UNION ALL SELECT '002', '001', 1 FROM dual UNION ALL SELECT '002', '001', 2 FROM dual UNION ALL SELECT '002', '001', 3 FROM dual UNION ALL SELECT '003', '002', 1 FROM dual UNION ALL SELECT '003', '002', 2 FROM dual UNION ALL SELECT '004', '001', 1 FROM dual ) select case when b.c_id = '001' then a.s_id end as "ID", case when b.c_id = '001' then min(a.s_nm) end as "성명", min(b.c_id) as "성별", min(b.c_nm) as "스터디", min((case when c.chasu = 1 then 'o' end)) as "1차", min((case when c.chasu = 2 then 'o' end)) as "2차", min((case when c.chasu = 3 then 'o' end)) as "3차", count(c.chasu) from student a , course b,study c where a.s_id = c.s_id (+) and b.c_id = c.c_id (+) group by a.s_id, b.c_id order by a.s_id, b.c_id ;
--듣지 않은 강의는 제외한 쿼리 WITH student AS ( SELECT '001' s_id, '기민용' s_nm FROM dual UNION ALL SELECT '002', '이현석' FROM dual UNION ALL SELECT '003', '김정식' FROM dual UNION ALL SELECT '004', '강정식' FROM dual ) , course AS ( SELECT '001' c_id, 'Database' c_nm FROM dual UNION ALL SELECT '002', 'Java' FROM dual ) , study AS ( SELECT '001' s_id, '001' c_id, 1 chasu FROM dual UNION ALL SELECT '001', '001', 3 FROM dual UNION ALL SELECT '001', '002', 2 FROM dual UNION ALL SELECT '002', '001', 1 FROM dual UNION ALL SELECT '002', '001', 2 FROM dual UNION ALL SELECT '002', '001', 3 FROM dual UNION ALL SELECT '003', '002', 1 FROM dual UNION ALL SELECT '003', '002', 2 FROM dual UNION ALL SELECT '004', '001', 1 FROM dual ) SELECT ST.S_ID , MAX(ST.S_NM) , C.C_ID , MAX(C.C_NM) , MAX(CASE WHEN S.CHASU = '1' THEN TO_CHAR('O') ELSE NULL END) AS "1차" , MAX(CASE WHEN S.CHASU = '2' THEN TO_CHAR('O') ELSE NULL END) AS "2차" , MAX(CASE WHEN S.CHASU = '3' THEN TO_CHAR('O') ELSE NULL END) AS "3차" , COUNT(CASE WHEN S.CHASU = '1' THEN '1' WHEN S.CHASU = '2' THEN '2' WHEN S.CHASU = '3' THEN '3' ELSE '0' END) AS "참여횟수" FROM STUDENT ST , COURSE C , STUDY S WHERE 1 = 1 AND ST.S_ID = S.S_ID(+) AND C.C_ID = S.C_ID(+) GROUP BY ST.S_ID, C.C_ID ORDER BY ST.S_ID ;
여기서 막히네요..
+
OUTER JOIN을 사용하기 위한 조건,
CASE문에 대해 잘 알 수 있었습니다.
이하 공부 후 정답 도출한 쿼리
WITH student AS ( SELECT '001' s_id, '기민용' s_nm FROM dual UNION ALL SELECT '002', '이현석' FROM dual UNION ALL SELECT '003', '김정식' FROM dual UNION ALL SELECT '004', '강정식' FROM dual ) , course AS ( SELECT '001' c_id, 'Database' c_nm FROM dual UNION ALL SELECT '002', 'Java' FROM dual ) , study AS ( SELECT '001' s_id, '001' c_id, 1 chasu FROM dual UNION ALL SELECT '001', '001', 3 FROM dual UNION ALL SELECT '001', '002', 2 FROM dual UNION ALL SELECT '002', '001', 1 FROM dual UNION ALL SELECT '002', '001', 2 FROM dual UNION ALL SELECT '002', '001', 3 FROM dual UNION ALL SELECT '003', '002', 1 FROM dual UNION ALL SELECT '003', '002', 2 FROM dual UNION ALL SELECT '004', '001', 1 FROM dual ) SELECT CASE WHEN A.c_id = '001' THEN a.s_id END AS "ID" , MAX(CASE WHEN A.c_id = '001' THEN A.s_nm END) AS "성명" , MAX(CASE WHEN A.C_NM = 'Database' THEN 'Database' WHEN A.C_NM = 'Java' THEN 'Java' ELSE '0' END) AS 스터디 , MAX(CASE WHEN S.CHASU = '1' THEN TO_CHAR('O') ELSE NULL END) AS "1차" , MAX(CASE WHEN S.CHASU = '2' THEN TO_CHAR('O') ELSE NULL END) AS "2차" , MAX(CASE WHEN S.CHASU = '3' THEN TO_CHAR('O') ELSE NULL END) AS "3차" , COUNT( S.CHASU) AS "참여횟수" FROM (SELECT ST.S_ID, ST.S_NM, C.C_ID, C.C_NM FROM student st, course C) A , study S WHERE 1 = 1 AND A.S_ID = S.S_ID(+) AND A.C_ID = S.C_ID(+) GROUP BY A.S_ID, A.C_ID ORDER BY A.S_ID ;
SQL 패턴이 많이 바뀌었군요
제가 배울때랑 많이 달라서 ....
아래 퀴리로 전 해결했읍니다 참고하세요
WITH student AS
(
SELECT '001' s_id, '기민용' s_nm
UNION ALL SELECT '002', '이현석'
UNION ALL SELECT '003', '김정식'
UNION ALL SELECT '004', '강정식'
)
, course AS
(
SELECT '001' c_id, 'Database' c_nm
UNION ALL SELECT '002', 'Java'
)
, study AS
(
SELECT '001' s_id, '001' c_id, 1 chasu
UNION ALL SELECT '001', '001', 3
UNION ALL SELECT '001', '002', 2
UNION ALL SELECT '002', '001', 1
UNION ALL SELECT '002', '001', 2
UNION ALL SELECT '002', '001', 3
UNION ALL SELECT '003', '002', 1
UNION ALL SELECT '003', '002', 2
UNION ALL SELECT '004', '001', 1
)
select case when c.c_id = '001' then s.s_id end s_id,
case when c.c_id = '001' then s.s_nm end s_nm,
c.c_id, c.c_nm,
(select top 1 'O' from study st where st.c_id = c.c_id and st.s_id = s.s_id and st.chasu = 1) chasu1,
(select top 1 'O' from study st where st.c_id = c.c_id and st.s_id = s.s_id and st.chasu = 2) chasu2,
(select top 1 'O' from study st where st.c_id = c.c_id and st.s_id = s.s_id and st.chasu = 3) chasu3,
(select count(st.c_id) from study st where st.c_id = c.c_id and st.s_id = s.s_id ) as totalcnt
from student s, course c
order by s.s_id, c.c_id