컴퓨터과학 챕터 1 약 10분

Ch1. SQLD 자격증 — SQL 기초와 SELECT 완전 정복

O
OIYO 편집부 기여자
1/4

SQLD 자격증이란?

**SQLD(SQL Developer, SQL 개발자)**는 한국데이터산업진흥원(K-DATA)이 주관하는 국가공인 자격증입니다. 데이터베이스와 SQL에 대한 기본 지식과 활용 능력을 검증하며, IT 직종 취업·승진에서 가장 많이 요구되는 자격증 중 하나입니다.

주관 기관: 한국데이터산업진흥원(K-DATA)
응시 자격: 제한 없음 (누구나 응시 가능)
공식 사이트: www.dataq.or.kr

시험 구조

구분내용
시험 과목1과목: 데이터 모델링의 이해 / 2과목: SQL 기본 및 활용
문항 수총 50문항 (객관식 40문항 + 단답형 10문항)
시험 시간80분
합격 기준총점 60점 이상, 과목별 40% 이상
시험 형식필기 시험 (PBT 방식)

합격률: 평균 약 40~50% 수준. 단순 암기보다 SQL 실습과 개념 이해를 병행해야 합격 가능합니다.


데이터 모델링 기초

데이터 모델링이란?

데이터 모델링이란 현실 세계의 정보를 데이터베이스에 저장할 수 있도록 추상화·구조화하는 작업입니다. SQLD 1과목의 핵심이며, 개념적→논리적→물리적 모델링의 3단계로 진행됩니다.

단계설명표현 방법
개념적 모델링업무 관점에서 핵심 개체와 관계 파악ERD (개체-관계 다이어그램)
논리적 모델링개념을 구체적인 속성과 관계로 표현정규화된 테이블 구조
물리적 모델링실제 DBMS에 맞게 구현DDL, 인덱스, 파티션 등

개체-관계 모델 (ERD)

ERD(Entity-Relationship Diagram)는 개체(Entity), 속성(Attribute), 관계(Relationship)로 데이터 구조를 표현합니다.

  • 개체(Entity): 독립적으로 존재하는 정보 단위 (예: 고객, 주문, 상품)
  • 속성(Attribute): 개체의 특성 (예: 고객ID, 고객명, 전화번호)
  • 관계(Relationship): 개체 간의 연관 (예: 고객이 주문을 한다)

카디널리티(Cardinality):

1:1  — 하나의 개체가 하나의 다른 개체와 대응 (예: 직원:사원증)
1:N  — 하나의 개체가 여러 개체와 대응 (예: 고객:주문)
M:N  — 여러 개체가 여러 개체와 대응 (예: 학생:강의)
      M:N 관계는 교차 테이블(Junction Table)로 분리해야 함

정규화 (Normalization)

정규화는 데이터 중복을 제거하고 데이터 무결성을 보장하기 위해 테이블 구조를 단계적으로 개선하는 과정입니다.

제1정규형 (1NF): 모든 속성이 원자값(더 이상 분해 불가)을 가져야 함

  • 위반 예: 전화번호 컬럼에 여러 번호를 콤마로 구분해 저장
  • 해결: 전화번호를 별도 테이블로 분리

제2정규형 (2NF): 1NF + 부분 함수적 종속 제거

  • 복합 기본키를 가진 테이블에서 기본키의 일부에만 종속된 속성을 분리
  • 위반 예: (학생ID, 강의ID) → 강의명이 강의ID에만 종속

제3정규형 (3NF): 2NF + 이행 함수적 종속 제거

  • A→B, B→C일 때 A→C 같은 이행 종속 제거
  • 위반 예: 직원ID → 부서ID → 부서명 (부서명을 별도 테이블로 분리)

반정규화(De-normalization): 성능 향상을 위해 의도적으로 정규화를 되돌리는 것. 조회 성능 개선이 목적이지만 데이터 중복과 갱신 이상 위험이 있음.


SQL 기초

SQL이란?

**SQL(Structured Query Language)**은 관계형 데이터베이스를 관리하고 조작하기 위한 표준 언어입니다. SQL은 목적에 따라 다음과 같이 분류됩니다.

분류전체 명칭주요 명령어설명
DDLData Definition LanguageCREATE, ALTER, DROP, TRUNCATE테이블·스키마 구조 정의
DMLData Manipulation LanguageSELECT, INSERT, UPDATE, DELETE데이터 조작
DCLData Control LanguageGRANT, REVOKE권한 부여·취소
TCLTransaction Control LanguageCOMMIT, ROLLBACK, SAVEPOINT트랜잭션 제어

SELECT 문 완전 정복

SELECT 문은 SQL의 핵심입니다. SQLD 시험의 2과목 대부분이 SELECT 관련 문제입니다.

SELECT 기본 구조와 실행 순서

SELECT   컬럼명1, 컬럼명2, ...   -- 5. 조회할 열 선택
FROM     테이블명                 -- 1. 어느 테이블에서
WHERE    조건식                   -- 2. 어떤 조건으로 필터
GROUP BY 그룹화 컬럼              -- 3. 그룹화
HAVING   그룹 조건                -- 4. 그룹 조건 필터
ORDER BY 정렬 기준                -- 6. 정렬

중요: SQL은 작성 순서와 실행 순서가 다릅니다. 실행 순서: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

WHERE 절 주요 조건

-- 비교 연산자
WHERE salary > 3000000

-- BETWEEN: 범위 조건 (경계값 포함)
WHERE hire_date BETWEEN '2020-01-01' AND '2022-12-31'

-- IN: 목록 중 하나
WHERE dept_id IN (10, 20, 30)

-- LIKE: 패턴 매칭
WHERE name LIKE '김%'      -- '김'으로 시작
WHERE name LIKE '%수%'     -- '수'가 포함
WHERE name LIKE '_민'      -- 두 글자이고 '민'으로 끝남

-- IS NULL / IS NOT NULL
WHERE bonus IS NULL
WHERE manager_id IS NOT NULL

GROUP BY와 HAVING

-- 부서별 평균 급여 조회 (평균 급여 300만원 이상인 부서만)
SELECT   dept_id, AVG(salary) AS avg_salary
FROM     employees
GROUP BY dept_id
HAVING   AVG(salary) >= 3000000
ORDER BY avg_salary DESC;

WHERE vs HAVING: WHERE는 개별 행을 필터 (GROUP BY 이전), HAVING은 그룹화된 결과를 필터 (GROUP BY 이후)


JOIN 완전 정복

JOIN은 두 개 이상의 테이블을 연결하여 데이터를 조회하는 연산입니다.

INNER JOIN (내부 조인)

두 테이블에서 조인 조건을 만족하는 행만 반환합니다.

-- 주문이 있는 고객만 조회
SELECT c.customer_name, o.order_date, o.amount
FROM   customers c
  INNER JOIN orders o ON c.customer_id = o.customer_id;

LEFT OUTER JOIN (왼쪽 외부 조인)

왼쪽 테이블의 모든 행을 반환하고, 오른쪽 테이블에 매칭이 없으면 NULL을 표시합니다.

-- 주문이 없는 고객도 포함하여 조회
SELECT c.customer_name, o.order_date
FROM   customers c
  LEFT OUTER JOIN orders o ON c.customer_id = o.customer_id;
-- 주문이 없는 고객은 order_date가 NULL로 표시됨

CROSS JOIN (교차 조인)

두 테이블의 모든 행의 조합을 반환합니다. m행 × n행 = m×n행.

SELECT * FROM colors CROSS JOIN sizes;
-- 색상 3가지 × 사이즈 4가지 = 12행 반환

JOIN 정리

JOIN 종류반환 행
INNER JOIN두 테이블 모두 조건 일치하는 행
LEFT OUTER JOIN왼쪽 테이블 전체 + 오른쪽 일치 행(없으면 NULL)
RIGHT OUTER JOIN오른쪽 테이블 전체 + 왼쪽 일치 행(없으면 NULL)
FULL OUTER JOIN양쪽 테이블 전체 (불일치는 NULL)
CROSS JOIN모든 행의 카테시안 곱

서브쿼리 (Subquery)

서브쿼리는 SQL 문 안에 포함된 또 다른 SELECT 문입니다.

단일행 서브쿼리

서브쿼리가 한 행만 반환. 단일행 비교 연산자(=, >, <, >=, <=, <>) 사용.

-- 평균 급여보다 높은 직원 조회
SELECT name, salary
FROM   employees
WHERE  salary > (SELECT AVG(salary) FROM employees);

다중행 서브쿼리

서브쿼리가 여러 행을 반환. IN, ANY, ALL 연산자 사용.

-- 영업부 직원과 같은 급여를 받는 다른 직원 조회
SELECT name, salary
FROM   employees
WHERE  salary IN (SELECT salary FROM employees WHERE dept = '영업부')
  AND  dept <> '영업부';

다중열 서브쿼리

서브쿼리가 여러 열을 반환.

-- 각 부서에서 가장 높은 급여를 받는 직원 조회
SELECT name, dept_id, salary
FROM   employees
WHERE  (dept_id, salary) IN (
  SELECT dept_id, MAX(salary)
  FROM   employees
  GROUP BY dept_id
);

스칼라 서브쿼리 & 인라인 뷰

-- 스칼라 서브쿼리: SELECT 절에서 단일값 반환
SELECT name,
       salary,
       (SELECT AVG(salary) FROM employees) AS avg_salary
FROM   employees;

-- 인라인 뷰: FROM 절에서 가상 테이블처럼 사용
SELECT dept_id, avg_salary
FROM   (SELECT dept_id, AVG(salary) AS avg_salary
        FROM   employees
        GROUP BY dept_id) AS dept_avg
WHERE  avg_salary > 3500000;

집계함수 (Aggregate Functions)

집계함수는 여러 행의 값을 계산하여 하나의 결과를 반환합니다.

함수설명NULL 처리
COUNT(*)전체 행 수NULL 포함
COUNT(컬럼)NULL이 아닌 값의 수NULL 제외
SUM(컬럼)합계NULL 무시
AVG(컬럼)평균NULL 무시 (분모에서도 제외)
MAX(컬럼)최댓값NULL 무시
MIN(컬럼)최솟값NULL 무시
SELECT
  COUNT(*)         AS total_rows,
  COUNT(bonus)     AS has_bonus,       -- bonus가 NULL이 아닌 행 수
  SUM(salary)      AS total_salary,
  AVG(salary)      AS avg_salary,
  MAX(salary)      AS max_salary,
  MIN(salary)      AS min_salary
FROM employees;

윈도우 함수 (Window Functions)

윈도우 함수는 파티션 내 행들 간의 계산을 수행합니다. GROUP BY와 달리 행을 집계하지 않고 각 행에 결과를 추가합니다.

기본 문법

함수명() OVER (
  PARTITION BY 그룹컬럼    -- 윈도우(파티션) 정의
  ORDER BY     정렬컬럼    -- 정렬 기준
)

순위 함수

SELECT
  name,
  dept_id,
  salary,
  RANK()       OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rank_val,
  DENSE_RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dense_rank_val,
  ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS row_num
FROM employees;
함수동점 처리예시 (동점 2명)
RANK()같은 순위, 다음 순위 건너뜀1, 2, 2, 4
DENSE_RANK()같은 순위, 연속1, 2, 2, 3
ROW_NUMBER()동점 없이 고유 번호1, 2, 3, 4

LAG / LEAD 함수

이전 행과 다음 행의 값을 현재 행에서 참조합니다.

SELECT
  order_date,
  amount,
  LAG(amount, 1)  OVER (ORDER BY order_date) AS prev_amount,   -- 이전 행
  LEAD(amount, 1) OVER (ORDER BY order_date) AS next_amount    -- 다음 행
FROM orders;

NULL 처리 함수

NULL은 “알 수 없음”을 의미하며, 일반 비교 연산자로는 비교할 수 없습니다.

-- NULL 관련 주의사항
NULL = NULL   -- 결과: NULL (TRUE가 아님!)
NULL <> NULL  -- 결과: NULL
-- NULL 비교는 반드시 IS NULL / IS NOT NULL 사용

-- NVL (Oracle): NULL이면 대체값 반환
SELECT NVL(bonus, 0) FROM employees;         -- bonus가 NULL이면 0

-- COALESCE (표준 SQL): 첫 번째 NULL이 아닌 값 반환
SELECT COALESCE(bonus, commission, 0) FROM employees;

-- NULLIF: 두 값이 같으면 NULL, 다르면 첫 번째 값 반환
SELECT NULLIF(score, 0) FROM students;       -- score가 0이면 NULL (0으로 나누기 방지에 활용)

-- CASE 문으로 NULL 처리
SELECT name,
       CASE WHEN bonus IS NULL THEN '보너스 없음'
            ELSE TO_CHAR(bonus) END AS bonus_info
FROM employees;

학습 체크리스트

  • SQLD 시험 구조(과목·문항·합격기준)를 설명할 수 있다
  • 데이터 모델링 3단계와 ERD 구성 요소를 설명할 수 있다
  • 제1~3정규형의 위반 사례와 해결 방법을 알고 있다
  • SELECT 문의 실행 순서(FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY)를 외웠다
  • INNER JOIN, LEFT OUTER JOIN, CROSS JOIN의 차이를 설명할 수 있다
  • 단일행·다중행·다중열 서브쿼리를 구분할 수 있다
  • COUNT(*) vs COUNT(컬럼)의 NULL 처리 차이를 안다
  • RANK, DENSE_RANK, ROW_NUMBER의 동점 처리 방식 차이를 안다
  • NVL, COALESCE, NULLIF의 차이를 설명할 수 있다

핵심 개념 카드

SELECT 실행 순서 ★★★★★ : FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. 작성 순서와 실행 순서가 다르다는 점이 시험 단골 출제 포인트. 암기 포인트: “프웨그해셀오” (FROM-WHERE-GROUP-HAVING-SELECT-ORDER)

WHERE vs HAVING ★★★★★ : WHERE는 개별 행 필터(GROUP BY 이전), HAVING은 그룹화된 결과 필터(GROUP BY 이후). 집계함수는 WHERE에서 사용 불가, HAVING에서만 사용 가능. 암기 포인트: WHERE=행 필터, HAVING=그룹 필터

RANK vs DENSE_RANK vs ROW_NUMBER ★★★★★ : RANK: 동점 시 같은 순위 부여, 다음 순위 건너뜀 (1,2,2,4). DENSE_RANK: 동점 허용, 연속 순위 (1,2,2,3). ROW_NUMBER: 동점 없이 고유 번호 (1,2,3,4). 암기 포인트: DENSE(밀집)는 빈 번호 없이 연속

INNER JOIN vs LEFT OUTER JOIN ★★★★★ : INNER JOIN은 양쪽 테이블에 모두 일치하는 행만 반환. LEFT JOIN은 왼쪽 테이블 전체 + 오른쪽 미일치 시 NULL. “고객이 주문을 했든 안 했든 모든 고객 보기”는 LEFT JOIN.

NULL 처리 연산자 ★★★★ : NULL과 어떤 값의 비교도 NULL. 반드시 IS NULL / IS NOT NULL 사용. NVL(Oracle)과 COALESCE(표준)는 NULL 대체값 반환. NULLIF는 두 값이 같을 때 NULL 반환. 암기 포인트: NULL = NULL은 FALSE가 아니라 NULL

정규화 1NF~3NF ★★★★ : 1NF=원자값, 2NF=부분함수종속 제거(복합키 테이블), 3NF=이행함수종속 제거. 반정규화는 성능을 위해 의도적으로 되돌리는 것.

집계함수와 NULL ★★★★ : COUNT(*)는 NULL 포함 전체 행 수. COUNT(컬럼)는 NULL을 제외한 행 수. SUM/AVG/MAX/MIN은 모두 NULL을 무시하고 계산.


실전 퀴즈

Q1. 다음 SQL의 실행 결과에서 순위 함수 RANK, DENSE_RANK, ROW_NUMBER의 차이는?

점수가 90, 90, 80인 3명의 경우: RANK()는 1,1,3 / DENSE_RANK()는 1,1,2 / ROW_NUMBER()는 1,2,3을 반환합니다. RANK는 동점자 수만큼 다음 순위를 건너뛰고, DENSE_RANK는 건너뛰지 않으며, ROW_NUMBER는 동점을 허용하지 않습니다.

Q2. WHERE salary > AVG(salary)라는 쿼리가 오류가 나는 이유는?

WHERE 절에서는 집계함수를 사용할 수 없습니다. 집계함수는 GROUP BY 이후에 적용되기 때문에 WHERE 처리 시점에는 값이 결정되지 않습니다. 올바른 방법은 서브쿼리를 사용하는 것입니다: WHERE salary > (SELECT AVG(salary) FROM employees).

Q3. COUNT(*)와 COUNT(bonus)의 차이는?

COUNT()는 NULL을 포함한 전체 행 수를 반환합니다. COUNT(bonus)는 bonus 컬럼이 NULL이 아닌 행의 수만 반환합니다. 따라서 bonus가 NULL인 직원이 있으면 COUNT() > COUNT(bonus)가 됩니다.

O

OIYO 편집부

Content Editor

지식 인큐베이터이자 전문 콘텐츠 크리에이터. 경영, 경제, 법률 및 실생활에 유용한 실무/자격증 중심의 깊이 있는 정보를 연구하고 공유합니다.