Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

쟝이의 세상

SQLD 기출문제 2과목(21~40) 오답정리 본문

자격증

SQLD 기출문제 2과목(21~40) 오답정리

zyangee 2024. 8. 11. 04:06
21. 실행 결과가 다른 하나는?
① SELECT DNAME, LOC, DEPTNO
     FROM DEPT
     ORDER BY DNAME, LOC, 3 DESC;
② SELECT DNAME, LOC AREA, DEPTNO
     FROM DEPT
     ORDER BY DNAME, AREA, DEPTNO DESC;
③ SELECT DNAME, LOC AREA, DEPTNO
     FROM DEPT
     ORDER BY 1, AREA, 3 DESC;
④ SELECT DNAME DEPT, LOC AREA, DEPTNO
     FROM DEPT
     ORDER BY DEPT DESC, LOC, 3 DESC;

 

SELECT DNAME, LOC, DEPTNO
FROM DEPT
ORDER BY DNAME, LOC, 3 DESC;

DNAME 오름차순 정렬, LOC 오름차순 정렬, 3(DEPTNO) 내림차순 정렬

-> 3: DEPT 테이블의 세번째 행

SELECT DNAME, LOC AREA, DEPTNO
FROM DEPT
ORDER BY DNAME, AREA, DEPTNO DESC;

DNAME 오름차순 정렬, AREA(LOC) 오름차순 정렬, DEPTNO 내림차순 정렬

-> AREA는 LOC 컬럼의 별칭

SELECT DNAME, LOC AREA, DEPTNO
FROM DEPT
ORDER BY 1, AREA, 3 DESC;

1(DNAME) 오름차순 정렬, AREA(LOC) 오름차순 정렬, 3(DEPTNO) 내림차순 정렬

-> 1: DEPT 테이블의 첫번째 행

-> AREA는 LOC 컬럼의 별칭

-> 3: DEPT 테이블의 세번째 행

SELECT DNAME DEPT, LOC AREA, DEPTNO
FROM DEPT
ORDER BY DEPT DESC, LOC, 3 DESC;

DEPT(DNAME) 내림차순 정렬, LOC 오름차순 정렬, 3(DEPTNO) 내림차순 정렬

-> DEPT는 DNAME 컬럼의 별칭

-> 3: DEPT 테이블의 세번째 행


22. 아래는 이름이 4문자 이상이고 2번째 문자가 S인 학번을 출력하는 SQL이다. 빈칸 ㉠에 들어갈 수 있는 내용으로 가장 적절하지 않은 것은?
SELECT 학번
FROM 학생
WHERE 학생.이름 LIKE ㉠
① '%S_ _ _'
'_S%_ _'
'_S_%_'
④ '_S_ _%'
  • %: 0개 이상의 문자
    • %com -> com으로 끝나는 문자
    • r% -> r로 시작하는 문자
    • e%a -> e로 시작하고 a로 끝나는 문자
    • %h% -> 몇 글자인지는 모르지만 중간에 h 가 들어가는 문자

① %S_ _ _ -> 앞에 몇 글자가 들어가는 지 모름. S가 첫 문자가 될 수도 있고, 다섯번째 문자가 될 수도 있음


23. 전공이름별로 묶어 전공이름과 학점 평균을 전공이름의 내림차순으로 정렬하여 출력하고자 할 때, 빈칸 ㉠, ㉡에 들어갈 명령어로 가장 적절한 것은?
SELECT 전공이름, AVG(학점)
FROM 전공, 학생
WHERE 전공.전공번호 = 학생.전공번호
㉠    전공이름
ORDER BY 전공이름 ㉡
① ㉠ GROUP BY  ㉡ DESC
② ㉠ HAVING  ㉡ DESC
㉠ GROUP BY  ㉡ ASC
④ ㉠ HAVING  ㉡ ASC

 

  • GROUP BY : 동일한 값을 가진 행을 그룹으로 묶어줌
  • HAVING : 집계함수의 조건절
  • ORDER BY : SELECT문에서 나온 결과를 정렬
    • ASC : 오름차순 (생략가능)
    • DESC : 내림차순

전공이름별로 묶어 전공이름과 학점 평균을 전공이름의 내림차순으로 정렬

-> GROUP BY, DESC


24. SQL의 실행 결과로 가장 적절하지 않은 것은?
① ROUND(4.875, 2) = 4.88
LENGTH('KOREAN') = 6
DATE_FORMAT('2022-11-02', '%Y-%m-%d') = 2022-11-02
④ SUBSTR('Gangneung Wonju', 8, 4) = 'g Wo'

 

  • ROUND('값', '자리수') : 값을 지정한 자리수(+1)에서 반올림
    • ROUND(123.567) : 자리수를 지정하지 않으면 소수점 아래의 자리를 출력하지 않음(소수점 첫째자리에서 반올림) = 124
    • ROUND(123.567, 0) : 소수점 0번째 자리까지 출력(소수점 첫째자리에서 반올림) = 124
      -> 0은 생략 가능
    • ROUND(123.567, 1) : 소수점 1번째 자리까지 출력(소수점 두번째 자리에서 반올림) = 123.6
    • ROUND(123.567, 2) : 소수점 2번째 자리까지 출력(소수점 세번째 자리에서 반올림) = 123.57
  • LENGTH('문자열') : 해당 문자열의 길이 출력
    • LENGTH('Oracle SQL') = 10
      -> 공백도 문자열로 취급
  • DATE_FORMAT('날짜', '형식') : 해당 날짜를 지정한 형식으로 출력
    • DATE_FORMAT('2024.08.09', '%Y.%m.%d') : 해당 날짜를 %Y(4자리년도).%m(월을 두자리 숫자).%d(일을 두자리로) 출력 = 2024.08.09
  • SUBSTR('문자열', '시작지점', '길이') : 해당 문자열을 시작지점부터 길이만큼 출력
    • SUBSTR('Hello World', 5, 3) : Hello World 문자열을 5번째 문자부터 3글자 출력 = 'o W'
      -> 공백도 문자열로 취급

④ SUBSTR('Gangneung Wonju', 8, 4) = 'ng W'

 


25. 아래를 참고할 때 광고매체 ID별 최초로 게시한 광고명과 광고시작일자를 출력하기 위하여 빈칸 ㉠에 들어갈 SQL로 가장 적절한 것은?


[SQL]
SELECT          C.광고매체명, B.광고명, A.광고시작일자
FROM             광고게시 A, 광고 B, 광고매체 C, ( ㉠ ) D
WHERE           A.광고시작일자 = D.광고시작일자
    AND             A.광고매체ID = D.광고매체ID
    AND             A.광고ID = B.광고ID
    AND             A.광고매체ID = C.광고매체ID
ORDER BY     C.광고매체명;
SELECT D.광고매체ID, MIN(D.광고시작일자) AS 광고시작일자
     FROM 광고게시 D
     WHERE D.광고매체ID = C.광고매체ID
     GROUP BY D.광고매체ID
SELECT 광고매체ID, MIN(광고시작일자) AS 광고시작일자
     FROM 광고게시
     GROUP BY 광고매체ID
SELECT MIN(광고매체ID) AS 광고매체ID, MIN(광고시작일자) AS 광고시작일자
     FROM 광고게시
     GROUP BY 광고ID
④ SELECT MIN(광고매체ID) AS 광고매체ID, MIN(광고시작일자) AS 광고시작일자
     FROM 광고게시

 

광고매체 ID별로 최초 게시 광고명, 광고시작일자
-> 우선 광고매체ID로 GROUP BY한 내용이 있어야 함

-> 최초로 게시한 광고시작일자는 제일 작은 값이므로 MIN( ) 함수 사용

WHERE A.광고시작일자 = D.광고시작일자
AND A.광고매체ID = D.광고매체ID
AND A.광고ID = B.광고ID
AND A.광고매체ID = C.광고매체ID

-> WHERE 절에서는 "광고게시 A, 광고 B, 광고매체 C, ( ㉠ ) D" 각각의 테이블을 JOIN하기 위한 문장이다.

 

① 
SELECT D.광고매체ID, MIN(D.광고시작일자) AS 광고시작일자
FROM 광고게시 D
WHERE D.광고매체ID = C.광고매체ID
GROUP BY D.광고매체ID

C는 괄호로 묶인 D의 서브쿼리에 없기 때문에 확인할 수 없는 테이블이다. -> 오류발생

⓷
SELECT MIN(광고매체ID) AS 광고매체ID, MIN(광고시작일자) AS 광고시작일자
FROM 광고게시
GROUP BY 광고ID

예시

광고매체ID : 광고매체를 구별하는 고유의 ID

광고ID별로 광고매체ID의 최솟값과 광고시작일자의 최솟값을 구하는 서브쿼리

-> 결과 : 광고ID별 광고매체ID가 최솟값인 광고매체명과 광고명, 광고시작일자의 최솟값(=최초 광고 시작일)

⓸
SELECT MIN(광고매체ID) AS 광고매체ID, MIN(광고시작일자) AS 광고시작일자
FROM 광고게시

예시

광고매체ID의 최솟값과 광고시작일자의 최솟값을 구하는 서브쿼리

-> 결과 : 출력되는 값이 없음


26. 아래 SQL을 순서대로 실행했을 때 최종적으로 반영되는 SQL을 모두 고른 것은?
(가) INSERT INTO emp (empno, ename, deptno) VALUES (999, 'Smith', 10);
       SAVEPOINT a;
(나) DELETE emp WHERE empno = 202;
       SAVEPOINT b;
(다) UPDATE emp SET ename = 'Clark';
       ROLLBACK TO SAVEPOINT a;
(라) INSERT INTO emp (empno, ename, deptno) VALUES (300, 'Thomas', 30);
       SAVEPOINT c;
(마) DELETE emp WHERE deptno = 20;
       COMMIT;
① (가), (나), (다), (라), (마)
② (가), (나), (다), (라)
③ (나), (다), (라), (마)
④ (가), (라), (마)

 

  • 트랜잭션의 단계
  1. Begin(시작) : 트랜잭션 시작, 데이터베이스 상태를 변경하는 작업 시작
  2. Execute(실행) : 트랜잭션에 포함된 SQL문이 실행 -> 데이터 삽입, 수정, 삭제 등의 작업
  3. Commit(커밋) : 트랜잭션 내의 모든 작업 성공적으로 완료 후 데이터베이스에 영구적으로 반영
  4. Rollback(롤백) : 데이터베이스의 상태를 트랜잭션 시작 전으로 되돌림
  • SAVEPOINT : 작업 단위 내에서 저장점을 설정
    • SAVEPOINT a : 작업 중인 지금의 상태를 세이브포인트 a에 저장
    • ROLLBACK TO SAVEPOINT b : 모든 트랜잭션을 취소하지 않고 세이브포인트 b로 돌아감
(가)
INSERT INTO emp (empno, ename, deptno) VALUES (999, 'Smith', 10);
SAVEPOINT a;

emp 테이블에 (999, 'Smith', 10) 행 삽입 후 savepoint a에 저장

(나)
DELETE emp WHERE empno = 202;
SAVEPOINT b;

emp 테이블의 empno가 202인 행 삭제 후 savepoint b에 저장

-> savepoint a와 b 존재

(다)
UPDATE emp SET ename = 'Clark';
ROLLBACK TO SAVEPOINT a;

emp 테이블의 ename을 'Clark'로 수정 후 savepoint a로 돌아감

-> WHERE 조건절이 없으므로 모든 행의 ename을 Clark로 수정

-> (가)만 실행된 상태로 되돌아감 -> (나)의 DELETE와 (다)의 UPDATE 실행 취소

(라)
INSERT INTO emp (empno, ename, deptno) VALUES (300, 'Thomas', 30);
SAVEPOINT c;

emp 테이블에 (300,'Thomas', 30) 행 삽입 후 savepoint c에 저장

-> (가)의 INSERT와 (라)의 INSERT만 실행된 상태

(마)
DELETE emp WHERE deptno = 20;
COMMIT;

emp 테이블의 deptno가 20인 행 삭제 후 데이터베이스에 실행한 트랜잭션 모두 반영

-> (가)의 INSERT와 (라)의 INSERT, (마)의 DELETE 실행됨

 

=> (가), (라), (마)

 

27. 아래 SQL의 실행 결과로 가장 적절한 것은?
[TABLE_A]


[SQL]
SELECT COLB, MAX(COLA) AS COLA1, MIN(COLA) AS COLA2, SUM(COLA + COLC) AS SUMAC
FROM TABLE_A
GROUP BY COLB;






 

SQL 실행 순서

: FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY

GROUP BY COLB

-> NULL도 그룹으로 묶어줘야 한다. (NULL을 제외하는건 집계함수)

MAX(COLA) AS COLA1

-> NULL 그룹의 최댓값은 없으므로 NULL 출력

-> 가, 나, 다 그룹의 최댓값은 집계함수( MAX( ) )

MIN(COLA) AS COLA2

-> NULL 그룹의 최소값은 없으므로 NULL 출력

-> 가, 나, 다 그룹의 최솟값은 집계함수( MIN( ) )이므로 NULL을 제외하여 최솟값을 구함

SUM(COLA + COLC) AS SUMAC

각 행의 SUM( )을 구한 후 GROUP으로 묶은 SUM( )을 구한다. =>

 

28. 아래 SQL의 실행 결과로 가장 적절한 것은?
[TBL]


SELECT ID FROM TBL
GROUP BY ID
HAVING COUNT(*) = 2
ORDER BY (CASE WHEN ID = 999 THEN 0 ELSE ID END)






 

SELECT ID FROM TBL
GROUP BY ID
HAVING COUNT(*) = 2

ID 컬럼을 기준으로 같은 값을 가진 행을 하나의 그룹으로 묶는다

-> 조건: 같은 값을 가진 행의 수가 2개인 그룹만 추출

= 100, 999

ORDER BY (CASE WHEN ID = 999 THEN 0 ELSE ID END)

ID가 999일 때 0으로 출력하고, 아닐 경우엔 원래의 ID로 출력한다. -> ORDER BY 절에서 한정

ORDER BY (CASE WHEN ~ THEN 0 ELSE ID ~) : 순서를 정렬하기 위한 숫자일 뿐, 실제로 출력되지는 않음

-> 999는 0, 100은 100 -> 0이 먼저 와야 하므로 결과적으로는 999가 제일 위에 출력됨을 알 수 있다.

 

29. 오류가 발생하는 SQL은?

SELECT        지역, SUM(매출금액) AS 매출금액
FROM           지역별매출
GROUP BY   지역
ORDER BY   매출금액 DESC;

SELECT        지역, 매출금액
FROM           지역별매출
ORDER BY   년 ASC;

SELECT        지역, SUM(매출금액) AS 매출금액
FROM           지역별매출
GROUP BY   지역
ORDER BY   년 DESC;

SELECT        지역, SUM(매출금액) AS 매출금액
FROM           지역별매출
GROUP BY   지역
HAVING        SUM(매출금액) > 1000
ORDER BY   COUNT(*) ASC;

 

FROM 지역별매출 지역별매출 테이블에서
GROUP BY 지역 지역별로 그룹을 묶고
SELECT 지역, SUM(매출금액) AS 매출금액 그룹으로 묶인 지역과 그룹별 총 매출금액(별칭: 매출금액)을 출력
ORDER BY 매출금액 DESC 출력된 그룹별 매출금액을 내림차순으로 정렬

 

FROM 지역별매출 지역별매출 테이블에서
SELECT 지역, 매출금액 지역과 매출금액을 추출
ORDER BY 년 ASC  년을 기준으로 오름차순 정렬

 

FROM 지역별매출 지역별매출 테이블에서
GROUP BY 지역 지역별로 그룹을 묶고
SELECT 지역, SUM(매출금액) AS 매출금액 그룹으로 묶인 지역과 그룹별 총 매출금액(별칭 : 매출금액)을 출력
ORDER BY 년 DESC 년을 기준으로 내림차순

만약 이러한 지역 테이블이 있다고 가정할 때

SELECT 지역, SUM(매출금액) AS 매출금액
FROM 지역별매출
GROUP BY 지역
  1. 지역별로 그룹으로 묶어준다. -> 서울, 경기, 부산 -> 세 개의 그룹이 만들어짐
  2. 그룹으로 묶인 지역과 그룹별 총 매출금액(별칭: 매출금액)을 출력

이러한 결과를 내는데 여기서 ORDER BY 년 DESC 하면 오류! -> 년을 기준으로 내림차순 하는 것은 불가능

 

FROM 지역별매출 지역별매출 테이블에서
GROUP BY 지역 지역별로 그룹을 묶고
HAVING SUM(매출금액) > 1000 조건: 각 지역 그룹의 매출금액 합계가 1000 초과인 행
SELECT 지역, SUM(매출금액) AS 매출금액 (조건을 만족하는) 그룹으로 묶인 지역과 그룹별 총 매출금액(별칭 : 매출금액)을 출력
ORDER BY COUNT(*) ASC 각 지역별 총 행의 갯수를 기준으로 오름차순

30. 아래 SQL의 실행 결과로 가장 적절한 것은?
SELECT TO_CHAR(TO_DATE('2019.02.25', 'YYYY.MM.DD') + 1/12/(60/30), 'YYYY.MM.DD HH24:MI:SS')
FROM DUAL;
① 2019.02.25 02:00:00
② 2019.02.25 01:30:00
③ 2019.02.25 01:00:00
④ 2019.02.25 00:30:00

 

  • TO_CHAR( ) : 날짜, 숫자 등의 값을 문자열로 변환하는 함수
    • TO_CHAR(SYSDATE, 'YYYY-MM-DD') -> "2024-08-07"
      SYSDATE: 오라클에서 현재 시스템의 날짜와 시간을 반환해주는 함수
  • TO_DATE( ) : 문자열 형식의 날짜를 날짜 형식으로 변환하는 함수
    • TO_DATE('2024-08-07', 'YYYY-MM-DD') -> 2024-08-07 문자열을 date 형식으로 변환 "2024-08-07"
    • TO_DATE('2024-08-07 23', 'YYYY-MM-DD HH24') 
      -> 해당 문자열을 date 형식으로 변환(+시간) "2024-08-07 23:00:00"
    • YYYY: 4자리 연도
      MM: 2자리 월
      DD: 2자리 일
      HH24: 24시간 형식의 시간
      MI: 분
      SS: 초
TO_DATE('2019.02.25', 'YYYY.MM.DD') + 1/12/(60/30)

'2019.02.25' 문자열을 지정한 날짜형식으로 변환 -> 2019.02.25

1/12/(60/30) : 1일을 12시간으로 나누고, 나눈 값을 [ (60/30)분=2분 ] 으로 나눔

-> 1/12/2 : 1일을 12시간으로 나누고, 나눈 값을 2분으로 나눔 = 1시간

=> 2019.02.25 01:00:00

SELECT TO_CHAR(TO_DATE('2019.02.25', 'YYYY.MM.DD') + 1/12/(60/30), 'YYYY.MM.DD HH24:MI:SS')
FROM DUAL;

TO_CHAR(2019.02.25 01:00:00 , 'YYYY.MM.DD HH24:MI:SS') = 2019.02.25 01:00:00


31. 실행결과가 NULL인 SQL은? (단, DBMS는 오라클로 가정)
⓵ SELECT COALESCE(NULL, 'A') FROM DUAL;
⓶ SELECT NULLIF('A', 'A') FROM DUAL;
⓷ SELECT NVL('A', NULL) FROM DUAL;
⓸ SELECT NVL(NULL, 0) + 10 FROM DUAL;

 

  • COALESCE('인자값1', '인자값2' ... ) : NULL이 아닌 인자값 반환 (NULL을 만나면 다음 자리수로 미룸)
    • COALESCE(NULL, 1, 2) = 1
    • COALESCE(NULL, NULL, 2) = 2
    • COALESCE(1, 2, NULL) = 1
  • NULLIF('표현식1', '표현식2) : 두 개의 표현식을 비교. 두 표현식이 같으면 NULL 반환, 그렇지 않으면 표현식1을 반환
    • NULLIF(10, 20) = 10
    • NULLIF(40, 40) = NULL
  • NVL('값', '대체값') : 특정 표현식이 NULL인 경우 대체값을 반환
    • NVL(score, 'F') : score 컬럼의 값이 NULL인 경우 F 반환
    • NVL(bonus, 0) : bonus 컬럼의 값이 NULL인 경우 0 반환
⓵
SELECT COALESCE(NULL, 'A') FROM DUAL;

-> NULL을 만나면 다음 자리 수로 미룸 = 'A'

⓶ 
SELECT NULLIF('A', 'A') FROM DUAL;

-> 두 값이 같으면 NULL출력, 다르면 첫번째 값을 출력 = NULL

⓷ 
SELECT NVL('A', NULL) FROM DUAL;

-> 첫번째 값이 NULL일 경우 두번째 값으로 출력, NULL이 아닐 경우 첫번째 값 그대로 출력 = 'A'

⓸ 
SELECT NVL(NULL, 0) + 10 FROM DUAL;

-> 첫번째 값이 NULL일 경우 두번째 값으로 출력, NULL이 아닐 경우 첫번째 값 그대로 출력 = 0


32. SELECT 문장의 실행 순서를 올바르게 나열한 것은?
⓵ SELECT - FROM - WHERE - GROUP BY - HAVING - ORDER BY
⓶ FROM - SELECT - WHERE - GROUP BY - HAVING - ORDER BY
⓷ FROM - WHERE - GROUP BY - HAVING - ORDER BY - SELECT
⓸ FROM - WHERE - GROUP BY - HAVING - SELECT - ORDER BY

 

기본적인 SELECT 문장의 실행 순서

: FROM - WHERE - GROUP BY - HAVING - SELECT - ORDER BY

 

서브쿼리가 포함된 SELECT 문장의 경우 

: 서브쿼리 먼저 실행 후 메인쿼리 실행

SELECT employee_id, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees WHERE department_id = 10);

만약 위와 같은 쿼리문이 있다고 하면 순서는 아래와 같다.

  1. 서브쿼리 (SELECT AVG(salary) FROM employees WHERE department_id = 10) 먼저 실행되어 부서ID가 10인 평균급여를 구한다.
  2. 메인쿼리의 FROM절 실행 - employees 테이블을 가져온다.
  3. WHERE절 실행 - employees 테이블의 급여가 서브쿼리 값보다 큰 직원들만 필터링
  4. 위의 결과를 모두 만족하는 employee_id와 salary를 출력한다.

33. 5개의 테이블로부터 필요한 칼럼을 조회하려고 할 때, 최소 몇 개의 JOIN 조건이 필요한가?
⓵ 2개
⓶ 3개
⓷ 4개
⓸ 5개

 

테이블이 N개 있으면, 각 테이블을 서로 연결해야한다. -> 최소 N-1개의 JOIN이 필요함

SELECT A.col1, B.col2, C.col3, D.col4, E.col5
FROM A
JOIN B ON A.key = B.key
JOIN C ON B.key = C.key
JOIN D ON C.key = D.key
JOIN E ON D.key = E.key;
SELECT A.col1, B.col2, C.col3, D.col4, E.col5
FROM A, B, C, D, E
WHERE A.key = B.key
  AND B.key = C.key
  AND C.key = D.key
  AND D.key = E.key;
< JOIN절로 테이블 간의 연결 > < WHERE절로 테이블 간의 연결 >

34. 출연료가 8888 이상인 영화명, 배우명, 출연료를 구하는 SQL로 가장 적절한 것은? (단, 밑줄 친 속성들은 테이블의 기본키이다.)
배우 ( 배우번호, 배우명, 성별 )
영화 ( 영화번호, 영화명, 제작년도 )
출연 ( 배우번호, 영화번호, 출연료 )






 

예시

FROM 배우, 영화, 출연 배우, 영화, 출연 테이블을 가져온다. ** 오류 **
WHERE 출연료 >= 8888
AND 출연.영화번호 = 영화.영화번호
AND 출연.배우번호 = 배우.배우번호
출연료가 8888 이상이며
출연 테이블과 영화 테이블을 영화번호를 통해 연결
출연 테이블과 배우 테이블을 배우번호를 통해 연결
SELECT 출연.영화명, 영화.배우명, 출연.출연료 ** 출연테이블에 영화명은 존재하지 않음
** 영화테이블에 배우명은 존재하지 않음.

 

FROM 영화, 배우, 출연 영화, 배우, 출연 테이블을 가져온다. **오류**
WHERE 출연.출연료 > 8888
AND 출연.영화번호 = 영화.영화번호
AND 영화.영화번호 = 배우.배우번호
출연료가 8888을 초과

** 영화.영화번호와 배우.배우번호이 같은 행은 존재하지 않음 -> 잘못된 조인 조건을 가지고 있다.
SELECT 영화.영화명, 배우.배우명, 출연료 WHERE 조건에 만족하는 영화테이블의 영화명, 배우테이블의 배우명, 출연료를 출력한다.

 

FROM 배우, 영화, 출연 배우, 영화, 출연 테이블을 가져온다. ** 오류가 나오지는 않지만, 명확하게 표시하지 않음
-> 잘못된 결과를 초래할 수 있다 **
WHERE 출연료 >= 8888
AND 영화번호 = 영화.영화번호
AND 배우번호 = 배우.배우번호
출연료가 8888 이상

** 영화번호와 영화.영화번호가 같은 조건인데 영화번호가 어느 테이블의 영화번호인지 명시되어 있지 않음.
-> 만약 배우, 영화, 출연 테이블에 모두 영화번호 컬럼이 있었다면 오류를 야기할 수 있다.
** 배우번호 = 배우.배우번호도 위와 동일
SELECT 영화명, 배우명, 출연료 조건에 만족하는 영화명, 배우명, 출연료 출력

 

FROM 배우, 영화, 출연 배우, 영화, 출연 테이블을 가져온다.
WHERE 출연료 >= 8888
AND 출연.영화번호 = 영화.영화번호
AND 출연.배우번호 = 배우.배우번호
출연료가 8888 이상
출연 테이블과 영화 테이블을 영화번호를 통해 연결
출연 테이블과 배우 테이블을 배우번호를 통해 연결
SELECT 영화.영화명, 배우.배우명, 출연료 조건에 만족하는 영화 테이블의 영화명, 배우 테이블의 배우명, 출연료를 출력

35. 아래에서 JOIN에 대한 설명으로 가장 적절한 것은?
(가) 일반적으로 조인은 PK와 FK값의 연관성에 의해 성립된다.
(나) DBMS 옵티마이저는 FROM 절에 나열된 테이블들을 임의로 3개 정도씩 묶어서 조인을 처리한다.
(다) EQUI JOIN은 조인에 관여하는 테이블 간의 칼럼 값들이 정확하게 일치하는 경우에 사용되는 방법이다.
(라) EQUI JOIN은 '=' 연산자에 의해서만 수행되며, 그 이외의 비ㅛㄱ 연산자를 사용하는 경우에는 모두 NON EQUI JOIN이다.
(마) 대부분 NON EQUI JOIN을 수행할 수 있지만, 때로는 설계쌍의 이유로 수행이 불가능한 경우도 있다.
⓵ (가), (다), (라)
⓶ (가), (나), (다)
⓷ (가), (나), (다), (라)
⓸ (가), (다), (라), (마)

 

  • DBMS 옵티마이저 : 가장 효율적인 방법으로 SQL을 수행할 최적의 처리 경로를 생성해주는 DBMS의 핵심 엔진
SELECT A.col1, B.col2, C.col3, D.col4, E.col5, F.col6
FROM A
JOIN B ON A.id = B.a_id
JOIN C ON B.id = C.b_id
JOIN D ON C.id = D.c_id
JOIN E ON D.id = E.d_id
JOIN F ON E.id = F.e_id
WHERE F.col6 > 100;
  • FROM 절에 나열된 테이블이 아무리 많아도 항상 2개의 테이블씩 짝을 지어 JOIN을 수행한다.
  • 항상 두 개의 테이블씩 조인하여 중간 결과를 생성

 

  • EQUI JOIN : 두 테이블을 동등 조건으로 결합하는 가장 기본적인 조인 방법
    • 주로 INNER JOIN 형태로 사용
    • "WHERE TB1.COL1 = TB2.COL1" : = 연산자를 사용해서 표현
  • NON EQUI JOIN : 두 테이블을 지정한 범주에 속하는 조건으로 결합하는 조인 방법
    • INNER JOIN 형태로 사용
    • "WHERE TB1.COL1 BETWEEN TB2.COL1 AND TB2.COL2" : = 연산자가 아닌 다른(between, <, >, <=, >=) 연산자들을 사용하여 조인 수행

 

36. 아래 SQL의 실행 결과로 가장 적절한 것은?



[SQL]
SELECT COUNT(*) CNT
FROM EMP_TBL A, RULE_TBL B
WHERE A.ENAME LIKE B.RULE;
⓵ 0
⓶ 2
⓷ 4
⓸ 6

 

LIKE 연산자 : 문자열의 패턴을 검색하는 데 사용

-> %: 모든 문자 / _: 한 글자

WHERE A.ENAME LIKE B.RULE

A 테이블의 ENAME 이 B 테이블의 RULE 컬럼과 같은 행을 추출

  1. S% 와 일치하는 행 : SMITH, SCOTT
  2. %T% 와 일치하는 행 : SMITH, SCOTT

=> 총 4개의 행 출력 = COUNT(*) CNT = 4


37. 순수 관계 연산자로 가장 적절하지 않은 것은?
⓵ SELECT
⓶ UPDATE
⓷ JOIN
⓸ DIVIDE

 

순수 관계 연산자 : 관계형 데이터베이스에서 관계의 연산을 수행하는 기본적인 연산자

-> SELECT, PROJECT, JOIN, DIVIDE

일반 집합 연산자 : 데이터베이스에서 집합 이론을 기반으로 한 연산, 데이터를 조작하는 데 사용

-> UNION, UNION ALL, INTERSECTION, DIFFERENCE, PRODUCT


38. 아래를 참고할 때 가장 적절한 SQL은?


[설명]
우리는 매일 배치작업을 통하여 고객에게 추천할 컨텐츠를 생성하고 고객에게 추천서비스를 제공한다.
추천 컨텐츠 엔터티에서 언제 추천을 해야 하는지를 정의하는 추천 대상일자가 있어 해당일자에만 컨텐츠를 추천해야 한다.
또한 고객이 컨텐츠를 추천 받았을 때 선호하는 컨텐츠가 아닌 경우에는 고객이 비선호컨텐츠로 분류하여 더 이상 추천받기를 원하지 않는다.
그러므로 우리는 비선호 컨텐츠 엔터티에 등록된 데이터에 대해서는 추천을 수행하지 않아야 한다.
👇🏻
추천 컨텐츠 엔터티에서 해당일자에만 컨텐츠 추천
선호하는 컨텐츠가 아닌 경우 비선호 컨텐츠로 분류되어 더이상 추천받지 X
비선호 컨텐츠 엔터티에 등록된 데이터 -> 추천 수행 X







 

바인딩 변수 : SQL 쿼리에서 동적으로 값을 전달할 때 사용하는 변수

-> 쉽게 말해서 값을 지정한다고 생각하면 쉬울 듯.

예시 테이블

FROM 고객 A INNER JOIN 추천컨텐츠 B
ON (A.고객ID = B.고객ID) INNER JOIN 컨텐츠 C
ON (B.컨텐츠ID = C.컨텐츠ID)
고객 테이블을 가져오고 별칭을 A라 한다.
고객 테이블과 추천컨텐츠 테이블을 고객ID 컬럼으로 연결
추천컨텐츠 테이블과 컨텐츠 테이블을 컨텐츠ID 컬럼으로 연결
1) WHERE A.고객ID = #custId#
  AND B.추천대상일자 = TO_CHAR(SYSDATE,'YYYY.MM.DD') 
2)  AND NOT EXISTS (SELECT X.컨텐츠ID
     FROM 비선호컨텐츠 X
     WHERE X.고객ID = B.고객ID)
1) 고객 테이블의 고객ID를 11이라고 입력했을 때,
고객ID가 11 이고, 추천컨텐츠의 추천대상일자가 현재 날짜여야되며,

** NOT EXISTS 서브쿼리의 결과
-> 존재하지 않을 경우 : 메인쿼리에 조건 포함 (TRUE 반환)
-> 존재할 경우 : 조건을 만족하는 데이터의 행은 결과에서 제외 (FALSE 반환)

2) 비선호컨텐츠 X에서 고객ID와 추천컨텐츠 C의 고객ID가 같을 경우의 컨텐츠ID가 존재하는지 확인 -> 존재
고객ID가 11인 행의 데이터는 제외하고 결과값 출력
SELECT C.컨텐츠ID, C.컨텐츠명 위 조건을 만족하는 컨텐츠 C의 컨텐츠ID와 컨텐츠명 출력

= 아무것도 출력되지 않음

 

1) FROM 고객 A
2)    INNER JOIN 추천컨텐츠 B
      ON (A.고객ID = #custId# AND A.고객ID = B.고객ID)
3)    INNER JOIN 컨텐츠 C
      ON (B.컨텐츠ID = C.컨텐츠ID)
4)   RIGHT OUTER JOIN 비선호컨텐츠 D
      ON (B.고객ID = D.고객ID AND B.컨텐츠ID = D.컨텐츠ID)
1) 고객테이블을 가져오고 별칭을 A라고 한다.
2) 고객 A과 추천컨텐츠 B를 고객ID로 연결 
   -> 고객ID=11인 고객만 필터링
3) 추천컨텐츠 B와 컨텐츠 C을 컨텐츠ID로 연결
4) 추천컨텐츠 B와 비선호컨텐츠 D를 RIGHT OUTER JOIN
   -> 비선호컨텐츠 테이블의 모든 행 포함
   -> 비선호컨텐츠를 기준으로 매칭되는 값을 가져온다.
   -> 매칭되지 않으면 NULL
WHERE
B.추천대상일자 = TO_CHAR(SYSDATE,'YYYY.MM.DD') 
  AND B.컨텐츠ID IS NOT NULL
추천컨텐츠 테이블의 추천대상일자가 현재 날짜이고,
추천컨텐츠 테이블의 컨텐츠ID가 NULL값이 아닌 조건
SELECT C.컨텐츠ID, C.컨텐츠명 위 조건을 만족하는 컨텐츠 C의 컨텐츠ID와 컨텐츠명 출력

= 아무것도 출력되지 않음

 

1) FROM 고객 A 
2)    INNER JOIN 추천컨텐츠 B ON (A.고객ID = B.고객ID) 
3)    INNER JOIN 컨텐츠 C ON (B.컨텐츠ID = C.컨텐츠ID) 
4)   LEFT OUTER JOIN 비선호컨텐츠 D
      ON (B.고객ID = D.고객ID AND B.컨텐츠ID = D.컨텐츠ID)
1) 고객 테이블을 가져오고 별칭을 A라고 한다.
2) 추천컨텐츠 B와 고객 A을 고객ID로 연결
3) 컨텐츠 C와 추천컨텐츠 B를 컨텐츠ID로 연결
4) 추천컨텐츠 B 와 비선호컨텐츠 D를 LEFT OUTER JOIN
   -> 추천컨텐츠의 모든 행 포함
   -> 추천컨텐츠를 기준으로 매칭되는 값을 가져온다.
   -> 매칭되지 않으면 NULL로 출력
   => 비선호컨텐츠의 값은 모두 NULL

WHERE A.고객ID = #custId#
  AND B.추천대상일자 = TO_CHAR(SYSDATE,'YYYY.MM.DD')
  AND D.컨텐츠ID IS NOT NULL
고객ID가 11이고,
추천컨텐츠 B의 추천대상일자가 현재 날짜이고,
비선호컨텐츠 D의 컨텐츠ID가 NULL값이 아닌 조건
SELECT C.컨텐츠ID, C.컨텐츠명 위 조건을 만족하는 컨텐츠 C의 컨텐츠ID와 컨텐츠명 출력

= 아무것도 출력되지 않음

 

1) FROM 고객 A
2)    INNER JOIN 추천컨텐츠 B
      ON (A.고객ID = #custId# AND A.고객ID = B.고객ID) 
3)    INNER JOIN 컨텐츠 C
      ON (B.컨텐츠ID = C.컨텐츠ID) 
1) 고객 테이블을 가져오고 별칭을 A라고 한다.
2) 고객 A와 추천컨텐츠 B를 고객ID로 연결
   -> 고객ID가 11인 고객만 필터링
3) 추천컨텐츠 B와 컨텐츠 C를 컨텐츠ID로 연결
1) WHERE B.추천대상일자 = TO_CHAR(SYSDATE,'YYYY.MM.DD') 
2)  AND NOT EXISTS (SELECT X.컨텐츠ID
     FROM 비선호컨텐츠 X
     WHERE X.고객ID = B.고객ID AND X.컨텐츠ID = B.컨텐츠ID)
1) 추천컨텐츠 B의 추천대상일자가 현재 날짜인 값
2) 비선호컨텐츠 X에서 고객ID와 추천컨텐츠 B의 고객ID가 같고,
비선호컨텐츠 X의 컨텐츠ID와 추천컨텐츠 B의 컨텐츠ID가 같은 행이 존재하는지 확인 -> 존재 X
 => TRUE 반환
SELECT C.컨텐츠ID, C.컨텐츠명 위 조건을 만족하는 컨텐츠 C의 컨텐츠ID와 컨텐츠명 출력

39. 아래에 대한 설명으로 가장 적절한 것은?
⓵ 제품, 생산제품, 생산라인 엔터티를 INNER JOIN 하기 위해서 생산제품 엔터티는 WHERE 절에 최소 3번 나타나야 한다.
⓶ 제품과 생산라인 엔터티를 JOIN 시 적절한 JOIN 조건이 없으므로 카타시안 곱(Cartesian Product)이 발생한다.
⓷ 제품과 생산라인 엔터티에는 생산제품과 대응되지 않는 레코드는 없다.
⓸ 특정 생산라인번호에서 생산되는 제품의 제품명을 알기 위해서는 제품, 생산제품, 생산라인까지 3개 엔터티의 INNER JOIN이 필요하다.

 

⓵ 제품, 생산제품 생산라인 엔터티 INNER JOIN

-> WHERE 제품.제품코드 = 생산제품.제품코드 AND 생산라인.라인번호 = 생상제품.라인번호 = 2번

 

⓶ 제품과 생산라인 엔터티 JOIN

-> 적절한 JOIN 조건이 없으므로 카타시안 곱 발생

 

⓷ 제품 - 생산제품 : 1:M 관계 / 생산라인 - 생산제품 : 1:M 관계

-> 생산제품과 대응되지 않는 레코드가 있을 수 있다.

-> 제품 엔터티의 행이 생산제품 엔터티에 존재하지 않을 수도 있음!

 

⓸ 특정 생산라인번호에서 생산되는 제품의 제품명 알기 위해서

-> 생산라인 - 생산제품 - 제품 3개의 테이블을 JOIN => INNER JOIN 2번!


40. 아래 SQL의 빈칸 ㉠, ㉡에 들어갈 내용으로 가장 적절한 것은?
[테이블]
고객 ( 고객번호, 이름, 등급 )
구매정보 ( 구매번호, 구매금액, 고객번호 )
* 구매정보 테이블의 고객번호는 고객 테이블의 고객번호를 참조하는 외래키(Foreign Key)이다.

[조건]
구매 이력이 있는 고객 중 구매 횟수가 3회 이상인 고객의 이름과 등급을 출력

[SQL]
SELECT A.이름, A.등급
FROM 고객 A

GROUP BY A.이름, A.등급
㉡ ;
⓵ ㉠ INNER JOIN 구매정보 B ON A.고객번호 = B.고객번호
     ㉡ HAVING SUM(B.구매번호) >= 3
⓶ ㉠ INNER JOIN 구매정보 B ON A.고객번호 = B.고객번호
     ㉡ HAVING COUNT(B.구매번호) >= 3
⓷ ㉠ LEFT OUTER JOIN 구매정보 B ON A.고객번호 = B.고객번호
     ㉡ HAVING SUM(B.구매번호) >= 3
⓸ ㉠ INNER JOIN 구매정보 B ON A.고객번호 = B.고객번호
     ㉡ WHERE B.구매번호 >= 3

 

구매 이력은? 구매정보 테이블, 고객의 이름과 등급은? 고객 테이블

-> 구매정보 테이블과 고객테이블을 JOIN => INNER JOIN

 

⓷ LEFT OUTER JOIN을 하면?

고객은 존재하지만 구매이력이 없는 고객이 존재할 수 있다. -> 구매정보 테이블에 매칭되지 않는 값은 NULL로 반환

--> SELECT, GROUP BY, HAVING 절을 통해 원하는 결과를 얻을 수 있음!

LEFT OUTER JOIN 구매정보 B ON A.고객번호 = B.고객번호
HAVING COUNT(B.구매번호) >= 3

: COUNT 함수에 특정 컬럼을 넣어주면 NULL을 제외하여 COUNT 한다.

 

예시 테이블

구매횟수가 3회 이상인 = COUNT(구매번호) >= 3

⓵ SUM(B.구매번호) >= 3 이라면 구매번호의 합이 3 이상인 조건을 만족하는 행 출력

⓸ B.구매번호 >= 3 이라면 구매번호의 값이 3 이상인 조건을 만족하는 행 출력