
의 범주에 해당하는 SQL 명령어로 가장 적절하지 않은 것은?
테이블의 구조를 생성, 변경, 삭제하는 등 데이터 구조를 정의하는 데 사용되는 명령어이다.
1️⃣ CREATE
2️⃣ GRANT
3️⃣ ALTER
4️⃣ DROP
📌 개념
SQL 문장 종류
SELECT, INSERT, UPDATE, DELETECREATE, ALTER, DROP, RENAMEGRANT, REVOKECOMMIT, ROLLBACK✅ 해설
2️⃣ (정답) GRANT는 DCL에 해당한다.
[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
📌 개념
✅ 해설
첫 번째 줄
COL1 > 1의 경우) 0은 조건을 충족하지 않음, NULL은 연산에서 제외COL1 IS NOT NULL의 경우) NULL을 제외한 두 행 조건 충족3️⃣ 90, NULL, 30, 60
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를 숫자와 비교할 때 자동으로 숫자로 변환
서비스번호 = 1와 TO_NUMBER(서비스번호) = 1는 현재 맥락에서 같은 의미✅ 해설
1️⃣ "하나라도 입력되어 있다면" -> 모든 값이 숫자로 변환가능한 형태여야 함
2️⃣ Empty String이 아닌 NULL이 입력됨
3️⃣ NULL은 비교 연산 결과가 NULL임 -> 연산에서 제외
4️⃣ (정답) SQL Server에서 Empty String과 NULL은 다른 의미를 가짐
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 절 이후에 올 수 있음
(가)
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'으로 바꾸라는 의미
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
✅ 해설
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
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'
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 구문의 실행순서
✅ 해설
3️⃣ ORDER BY는 SELECT 이후에 실행
-> 정렬 불가
1️⃣ SELECT
2️⃣ UPDATE
3️⃣ JOIN
4️⃣ DIVIDE
📌 개념
순수 관계 연산자
✅ 해설
4️⃣ (정답)

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

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로 생산제품에 있으니까.

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이라는 구문은 없음

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

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번과 동일함