[SQLD 학습 정리] 노랭이 오답노트 과목 2, 제 1장 - SQL 기본

도비·2025년 3월 6일

SQLD

목록 보기
5/5

6. 아래 내용

의 범주에 해당하는 SQL 명령어로 가장 적절하지 않은 것은?

테이블의 구조를 생성, 변경, 삭제하는 등 데이터 구조를 정의하는 데 사용되는 명령어이다. 

1️⃣ CREATE
2️⃣ GRANT
3️⃣ ALTER
4️⃣ DROP

📌 개념
SQL 문장 종류

  • DML(데이터 조작어) : 값을 조작하는 명령어
    - ex) SELECT, INSERT, UPDATE, DELETE
  • DDL(데이터 정의어) : 구조를 정의하는 명령어
    - ex) CREATE, ALTER, DROP, RENAME
  • DCL(데이터 제어어 : 접근 및 권한을 관리하는 명령어
    - ex) GRANT, REVOKE
  • TCL(트랜잭션 제어어) : 트랜잭션을 관리(제어)하는 명령어
    - ex) COMMIT, ROLLBACK

✅ 해설
2️⃣ (정답) GRANT는 DCL에 해당한다.


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

[SQL]
SELECT SUM(COL2) + SUM(COL3) FROM TAB_A;
SELECT SUM(COL2) + SUM(COL3) FROM TAB_A WHERE COL1 > 0;
SELECT SUM(COL2) + SUM(COL3) FROM TAB_A WHERE COL1 IS NOT NULL;
SELECT SUM(COL2) + SUM(COL3) FROM TAB_A WHERE COL1 IS NULL;

[TAB_A]
------------------
COL1   COL2   COL3
30     NULL   20
NULL   50     10
0      10     NULL
------------------

1️⃣ 60, NULL, 30, 60
2️⃣ 60, 20, 30, 60
3️⃣ 90, NULL, 30, 60
4️⃣ 90, 20, 30, 60

📌 개념

  • NULL은 일반적으로 연산에서 제외된다.
  • SUM에서 연산 대상 값이 없다면 (모두 NULL이라면) NULL을 반환한다.

✅ 해설
첫 번째 줄

  • SUM(COL2) = 60, SUM(COL3) = 30, SUM(COL2) + SUM(COL3) = 90
    두 번째 줄
  • COL1 > 1의 경우) 0은 조건을 충족하지 않음, NULL은 연산에서 제외
  • SUM(COL2) = NULL, SUM(COL3) = 20, SUM(COL2) + SUM(COL3) = NULL
    세 번째 줄
  • COL1 IS NOT NULL의 경우) NULL을 제외한 두 행 조건 충족
  • SUM(COL2) = 10, SUM(COL3) = 20, SUM(COL2) + SUM(COL3) = 30
    네 번째 줄
  • COL1 IS NULL의 경우) COL1이 NULL인 두번째 열만 조건 충족
  • SUM(COL2) = 50, SUM(COL3) = 10, SUM(COL2) + SUM(COL3) = 60

3️⃣ 90, NULL, 30, 60


11. 아래에 대한 설명으로 가장 적절한 것은?

CREATE TABLE 서비스
(
	서비스번호 VARCHAR2(10) PRIMARY KEY,
	서비스명 VARCHAR2(100) NULL,
	개시일자 DATE NOT NULL
);

[SQL]
ㄱ. SELECT * FROM 서비스 WHERE 서비스번호 = 1;
ㄴ. INSERT INTO 서비스 VALUES ('999', '', '2015-11-11');
ㄷ. SELECT * FROM 서비스 WHERE 서비스명 = '';
ㄹ. SELECT * FROM 서비스 WHERE 서비스명 IS NULL;

1️⃣ 서비스번호 칼럼의 레코드 중 '001'과 같은 숫자 형식으로 된 레코드가 하나라도 입력되어 있다면 ㄱ은 오류없이 실행된다.
2️⃣ 오라클에서 ㄴ과 같이 데이터를 입력하였을 때, 서비스명 칼럼에 공백문자 데이터가 입력된다.
3️⃣ 오라클에서 ㄴ과 같이 데이터를 입력하고 ㄷ과 같이 조회하였을 때, 데이터는 조회된다.
4️⃣ SQL Server에서 ㄴ과 같이 데이터를 입력하고 ㄹ과 같이 조회하였을 때, 데이터는 조회되지 않는다.

📌 개념
Oracle의 VARCHAR2에서는 ''(Empty String)이 NULL로 변환됨
<-> SQL Server에서는 ''(Empty String)이 NULL을 의미하지는 않음
Oracle에서 VARCHAR2를 숫자와 비교할 때 자동으로 숫자로 변환

  • 서비스번호 = 1TO_NUMBER(서비스번호) = 1는 현재 맥락에서 같은 의미

✅ 해설
1️⃣ "하나라도 입력되어 있다면" -> 모든 값이 숫자로 변환가능한 형태여야 함
2️⃣ Empty String이 아닌 NULL이 입력됨
3️⃣ NULL은 비교 연산 결과가 NULL임 -> 연산에서 제외
4️⃣ (정답) SQL Server에서 Empty String과 NULL은 다른 의미를 가짐


14. GROUP BY 절과 HAVING 절에 대한 설명으로 가장 적절한 것은?

1️⃣ 집계 함수의 통계 정보는 NULL 값을 가진 행을 포함하여 수행한다.
2️⃣ GROUP BY 절에서는 SELECT 절과 같이 ALIAS 명을 사용할 수 있다.
3️⃣ 집계 함수는 WHERE 절에도 올 수 있다.
4️⃣ HAVING 절은 일반적으로 GROUP BY 절 뒤에 위치한다.

📌 개념

✅ 해설
1️⃣ NULL을 제외하고 수행
2️⃣ GROUP BY 절은 ALIAS를 갖지 않음 (GROUP BY가 SELECT보다 먼저 실행됨, HAVING도 마찬가지)
3️⃣ 집계 함수는 WHERE 절 이후에 올 수 있음

  • WHERE은 개별 행을 필터링하는 기능, 집계 함수는 WHERE을 통해 필터링된 데이터로 집계 (그래서 HAVING을 사용 - 그룹을 필터링)
    4️⃣ (정답)

17. 아래의 (가)와 (나)가 동일한 결과를 출력한다고 할 때, 빈칸 ㄱ 에 들어갈 내용으로 가장 적절한 것은? (단, 스칼라 서브쿼리는 제외함)

(가)
SELECT LOC,
	CASE WHEN LOC = 'NEW YORK' THEN 'EAST'
	ELSE 'ETC'
	END as AREA
(나)
SELECT LOC,
	( ㄱ ) as AREA
FROM DEPT;

1️⃣ CASE WHEN LOC IS 'NEW YORK' THEN 'EAST' ELSE 'ETC' END
2️⃣ CASE LOC WHEN 'NEW YORK' THEN 'EAST' ELSE 'ECT' END
3️⃣ CASE LOC WHEN 'NEW YORK' THEN 'EAST' DEFAULT 'ECT' END
4️⃣ DECODE (LOC, 'EAST', 'NEW YORK', 'ECT')

📌 개념
CASE

CASE
	WHEN 조건1 THEN 결과1
	WHEN 조건2 THEN 결과2
	ELSE 기본값
END

DECODE

DECODE(컬럼, 조건1, 결과1, 조건2, 결과2, 기본값)

✅ 해설
1️⃣ IS라는 연산자는 없음 (IS NULL, IS TRUE 등 제외)
2️⃣ LOC 컬럼을 기준으로, 값이 'NEW YORK'이라면 'EAST'로, 그 외는 'ECT'
3️⃣ DEFAULT가 아니라 ELSE가 맞는 표현
4️⃣ 이 구문은 LOC이 'EAST'일 때, 'NEW YORK'으로 바꾸라는 의미


21. 실행 결과가 다른 하나는?

1️⃣

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

2️⃣

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

3️⃣

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

4️⃣

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

📌 개념
ALIAS

  • AS를 통해 별칭 부여 가능 ``
  • 특정 DB에서는 생략 가능
    ORDER BY에서 숫자는 해당 인덱스에 있는 항목을 의미함

✅ 해설
1️⃣ DNAME - ASC, LOC - ASC, DEPTNO - DESC
2️⃣ DNAME - ASC, LOC - ASC, DEPTNO - DESC
3️⃣ DNAME - ASC, LOC - ASC, DEPTNO - DESC
4️⃣ (정답) DNAME - DESC, LOC - ASC, DEPTNO - DESC


24. SQL의 실행 결과로 가장 적절하지 않은 것은?

1️⃣ ROUND(4.875, 2) = 4.88
2️⃣ LENGTH('KOREAN') = 6
3️⃣ DATE_FORMAT('2022-11-02', '%Y-%m-%d') = 2022-11-02
4️⃣ SUBSTR('Gangneung Wonju', 8, 4) = 'g Wo'

✅ 해설
1️⃣ ROUND(N, M)은 M째 자리까지 반올림 -> ROUND(4.875, 2) = 4.88
4️⃣ SUBSTR에서 인덱스는 1부터 시작 -> SUBSTR('Gangneung Wonju', 8, 4) = 'ng W'


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

1️⃣

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

2️⃣

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

3️⃣

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

4️⃣

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

📌 개념
SQL 구문의 실행순서

  • FROM + JOIN -> ON -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY

✅ 해설
3️⃣ ORDER BY는 SELECT 이후에 실행

  • SELECT는 필터링 기능, 즉 SELECT를 거친 후에는 '지역'과 '매출금액' 속성만 남음
  • SELECT에는 '년'이 존재하지 않음

-> 정렬 불가


37. 순수 관계 연산자로 가장 적절하지 않은 것은?

1️⃣ SELECT
2️⃣ UPDATE
3️⃣ JOIN
4️⃣ DIVIDE

📌 개념
순수 관계 연산자

  • 릴레이션 간의 연산을 정의하는 이론적 개념
  • SELECT, JOIN, UPDATE ...
    cf. DIVIDE는 SQL 표준 연산이 아님

✅ 해설
4️⃣ (정답)


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

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

SELECT C.컨텐츠ID, C.컨텐츠명
FROM 고객 A INNER JOIN 추천컨텐츠 B 
    ON (A.고객ID = B.고객ID) INNER JOIN 컨텐츠 C 
    ON (B.컨텐츠ID = C.컨텐츠ID)
WHERE A.고객ID = #custId#
    AND B.추천대상일자 = TO_CHAR(SYSDATE, 'YYYY.MM.DD')
    AND NOT EXISTS (
        SELECT X.컨텐츠ID
        FROM 비선호컨텐츠 X
        WHERE X.고객ID = B.고객ID);

2️⃣

SELECT C.컨텐츠ID, C.컨텐츠명
FROM 고객 A INNER JOIN 추천컨텐츠 B 
    ON (A.고객ID = #custId# AND A.고객ID = B.고객ID) INNER JOIN 컨텐츠 C 
    ON (B.컨텐츠ID = C.컨텐츠ID) RIGHT OUTER JOIN 비선호컨텐츠 D 
    ON (B.컨텐츠ID = D.컨텐츠ID AND B.컨텐츠ID = D.컨텐츠ID)
WHERE B.추천대상일자 = TO_CHAR(SYSDATE, 'YYYY.MM.DD')
    AND B.컨텐츠ID IS NOT NULL;

3️⃣

SELECT C.컨텐츠ID, C.컨텐츠명
FROM 고객 A INNER JOIN 추천컨텐츠 B 
    ON (A.고객ID = B.고객ID) INNER JOIN 컨텐츠 C 
    ON (B.컨텐츠ID = C.컨텐츠ID) LEFT OUTER JOIN 비선호컨텐츠 D 
    ON (B.컨텐츠ID = D.컨텐츠ID AND B.컨텐츠ID = D.컨텐츠ID)
WHERE A.고객ID = #custId#
    AND B.추천날짜 = TO_CHAR(SYSDATE, 'YYYY.MM.DD')
    AND D.컨텐츠ID IS NOT NULL;

4️⃣

SELECT C.컨텐츠ID, C.컨텐츠명
FROM 고객 A INNER JOIN 추천컨텐츠 B 
    ON (A.고객ID = #custId# AND A.고객ID = B.고객ID) INNER JOIN 컨텐츠 C 
    ON (B.컨텐츠ID = C.컨텐츠ID)
WHERE B.추천날짜 = TO_CHAR(SYSDATE, 'YYYY.MM.DD')
    AND NOT EXISTS (
        SELECT X.컨텐츠ID
        FROM 비선호컨텐츠 X
        WHERE X.고객ID = B.고객ID
        AND X.컨텐츠ID = B.컨텐츠ID
    );

📌 개념
AND NOT EXIST : 특정 조건을 만족하는 서브쿼리가 존재하지 않을 때 TRUE를 반환

✅ 해설
1️⃣ NOT EXIST절에서 고객 ID 일치만 확인 -> 비선호 컨텐츠가 있으면 모든 컨텐츠가 추천에서 배제
2️⃣ RIGHT OUTER JOIN 비선호컨텐츠 D <- 비선호 컨텐츠 조회됨
3️⃣ LEFT OUTER JOIN + D.컨텐츠ID IS NOT NULL → 비선호 컨텐츠 조회됨
4️⃣ (정답) WHERE절에 비선호컨텐츠에 존재하지 않는 것을 쿼리


39.아래에 대한 설명으로 가장 적절한 것은?

1️⃣ 제품, 생산제품, 생산라인 엔터티를 INNER JOIN하기 위해서 생산제품 엔터티는 WHERE 절에 최소 3번 나타나야 한다.
2️⃣ 제품과 생산라인 엔터티를 JOIN시 적절한 조인 조건이 없으므로 카티시안 곱(Cartesian Product)이 발생한다.
3️⃣ 제품과 생산라인 엔터티에는 생산제품과 대응되지 않는 레코드는 없다.
4️⃣ 특정 생산라인번호에서 생산되는 제품의 제품명을 알기 위해서는 제품, 생산제품, 생산라인까지 3개 엔터티의 INNER JOIN이 필요하다.

📌 개념

✅ 해설
1️⃣ 2번
2️⃣ (정답)
3️⃣ 대응되지 않는 레코드가 있을 수 있다. (0~N : 1로 대응됨)
4️⃣ 제품과 생산라인을 INNER JOIN 하면 됨 - 라인번호가 FK로 생산제품에 있으니까.


41. 아래를 참고할 때 시간대별사용량 테이블을 기반으로 고객별 사용금액을 출력하는 SQL로 가장 적절한 것은?

1️⃣

SELECT A.고객ID, A.고객명, SUM(B.사용량 * C.단가) AS 사용금액
FROM 고객 A INNER JOIN 시간대별사용량 B 
    ON (A.고객ID = B.고객ID) INNER JOIN 시간대구간 C 
    ON (B.사용시간대 <= C.시작시간대 AND B.사용시간대 >= C.종료시간대)
GROUP BY A.고객ID, A.고객명
ORDER BY A.고객ID, A.고객명;

2️⃣

SELECT A.고객ID, A.고객명, SUM(B.사용량 * C.단가) AS 사용금액
FROM 고객 A INNER JOIN 시간대별사용량 B INNER JOIN 시간대구간 C
    ON (A.고객ID = B.고객ID AND B.사용시간대 BETWEEN C.시작시간대 AND C.종료시간대)
GROUP BY A.고객ID, A.고객명
ORDER BY A.고객ID, A.고객명;

3️⃣

SELECT A.고객ID, A.고객명, SUM(B.사용량 * C.단가) AS 사용금액
FROM 고객 A 
INNER JOIN 시간대별사용량 B 
    ON (A.고객ID = B.고객ID) 
INNER JOIN 시간대구간 C 
    ON B.사용시간대 BETWEEN C.시작시간대 AND C.종료시간대
GROUP BY A.고객ID, A.고객명
ORDER BY A.고객ID, A.고객명;

4️⃣

SELECT A.고객ID, A.고객명, SUM(B.사용량 * C.단가) AS 사용금액
FROM 고객 A INNER JOIN 시간대별사용량 B 
    ON (A.고객ID = B.고객ID) BETWEEN JOIN 시간대구간 C
GROUP BY A.고객ID, A.고객명
ORDER BY A.고객ID, A.고객명;

📌 개념

✅ 해설
1️⃣ BETWEEN으로 해야함 (화살표를 써도 가능하지만 방향이 맞지 않음)
2️⃣ 각 JOIN마다 ON절이 필요함 (A INNER JOIN B INNER JOIN C ON... 가 아니라, 적어도 갯수는 맞아야)
3️⃣ (정답)
4️⃣ BETWEEN JOIN이라는 구문은 없음


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

📌 개념
LEFT OUTER JOIN이고 ON절은 C1 값이 같고 오른쪽 테이블의 C2가 1~3이어야 한다는 조건이다.
TAB1을 순회하며...

  • 왼쪽 테이블 레코드 -(사유)> 오른쪽 테이블 레코드
  • A, 1 -(A가 없음) -> NULL, NULL
  • B, 2 --> B, 2
  • C, 3 --> C, 3
  • D, 4 -(C1 = D인 레코드의 C2가 3보다 큼)-> NULL, NULL
  • E, 5 -(E가 없음)-> NULL, NULL
    ✅ 해설
    2️⃣ (정답)
    C1, C2, C1, C2
    A, 1, NULL, NULL
    B, 2, B, 2
    C, 3, C, 3
    D, 4, NULL, NULL
    E, 5, NULL, NULL

49. 아래의 오라클 SQL을 동일한 결과를 출력하는 ANSI 표준 구문으로 변경하고자 할 때 가장 적절한 SQL은?

1️⃣

SELECT A.게시판ID, A.게시판명, COUNT(B.게시글ID) AS CNT
FROM 게시판 A LEFT OUTER JOIN 게시글 B
ON (A.게시판ID = B.게시판ID AND B.삭제여부 = 'N')
WHERE A.사용여부 = 'Y'
GROUP BY A.게시판ID, A.게시판명
ORDER BY A.게시판ID;

2️⃣

SELECT A.게시판ID, A.게시판명, COUNT(B.게시글ID) AS CNT
FROM 게시판 A LEFT OUTER JOIN 게시글 B
ON (A.게시판ID = B.게시판ID AND A.사용여부 = 'Y')
WHERE B.삭제여부 = 'N'
GROUP BY A.게시판ID, A.게시판명
ORDER BY A.게시판ID;

3️⃣

SELECT A.게시판ID, A.게시판명, COUNT(B.게시글ID) AS CNT
FROM 게시판 A LEFT OUTER JOIN 게시글 B
ON (A.게시판ID = B.게시판ID)
WHERE A.사용여부 = 'Y'
AND B.삭제여부 = 'N'
GROUP BY A.게시판ID, A.게시판명
ORDER BY A.게시판ID;

4️⃣

SELECT A.게시판ID, A.게시판명, COUNT(B.게시글ID) AS CNT
FROM 게시판 A RIGHT OUTER JOIN 게시글 B
ON (A.게시판ID = B.게시판ID AND A.사용여부 = 'Y' AND B.삭제여부 = 'N')
GROUP BY A.게시판ID, A.게시판명
ORDER BY A.게시판ID;

📌 개념
ORACLE -> ANSI 표준
A = B(+) -> RIGHT OUTER JOIN
A(+) = B -> LEFT OUTER JOIN

✅ 해설
보기의 SQL

SELECT A.게시판ID, A.게시판명, COUNT(B.게시글ID) AS CNT
FROM 게시판 A, JOIN 게시글 B -> ANSI : FROM 게시판 A LEFT OUTER JOIN 게시글 B
WHERE A.게시판ID = B.게시판ID(+) -> ANSI : ON (A.게시판ID = B.게시판ID
AND B.삭제여부(+) = 'N' -> ANSI : AND B.삭제여부 = 'N')
AND A.사용여부 = 'Y' -> ANSI : WHERE A.사용여부 = 'Y'
GROUP BY A.게시판ID, A.게시판명
ORDER BY A.게시판ID;

1️⃣ (정답) ANSI 표준으로 바꾸면 1번과 동일함


profile
문과 였던 것...

0개의 댓글