SQL 개발자(SQLD) 시험 노트개념 정리15 MIN
SELECT 문과 산술·합성 연산자
SQLD 2과목의 둘째 자리입니다. SELECT·FROM의 기본 구조에서 시작해 컬럼 별칭과 AS, DISTINCT, 산술 연산자의 우선순위, 문자열을 잇는 합성 연산자, 그리고 NULL이 섞인 산술 연산의 결과까지 정리합니다.
앞 노트에서 SQL 문장의 갈래를 나눴습니다. 그중 실제 시험 문항의 절반 이상이 SELECT 하나에서 나옵니다. 이 절은 그 SELECT의 뼈대와, 조회한 값을 계산하거나 이어 붙이는 연산자를 다룹니다. 특히 NULL이 낀 산술 연산은 회차마다 나오는 자리입니다.
이 절의 예제는 아래 사원 테이블을 씁니다.
| 사원명 | 부서코드 | 급여 | 상여 |
|---|---|---|---|
| 홍길동 | D01 | 300 | 50 |
| 김철수 | D01 | 250 | NULL |
| 이영희 | D02 | 400 | 100 |
SELECT 문의 기본 구조
SELECT는 무엇을 볼지, FROM은 어디서 볼지를 적는 자리입니다. 둘은 언제나 함께 쓰이고 순서를 바꿀 수 없습니다.
SELECT와 FROM
SELECT 사원명, 급여
FROM 사원;
SELECT 뒤에 컬럼 이름을 쉼표로 늘어놓으면 그 컬럼만, *를 적으면 테이블의 모든 컬럼이 나옵니다. 결과의 컬럼 순서는 SELECT 뒤에 적은 순서를 따르므로 테이블에 정의된 차례와 달라도 됩니다.
컬럼 자리에는 값을 그대로 적을 수도 있습니다. SELECT '재직' AS 구분, 사원명 FROM 사원;처럼 쓰면 재직이라는 글자가 모든 행에 한 번씩 붙어 나옵니다. 값 하나가 한 줄로 나오는 것이 아니라 조회된 행 수만큼 되풀이된다는 점이 문항이 됩니다.
대소문자와 세미콜론
SQL의 예약어와 테이블·컬럼 이름은 대소문자를 가리지 않습니다. select와 SELECT가 같고 사원과 사원도 같습니다. 다만 작은따옴표로 감싼 값은 대소문자를 가립니다 — 'D01'과 'd01'은 다른 값입니다. 문장의 끝에는 세미콜론을 찍어 여기까지가 한 문장임을 알립니다.
컬럼 별칭
별칭은 결과에 나올 컬럼 이름을 다시 붙이는 것입니다. 계산식이 그대로 머리글이 되면 읽기 어려우므로 이름을 새로 줍니다.
AS와 생략
SELECT 사원명 AS 이름,
급여 * 12 연봉
FROM 사원;
AS는 붙여도 되고 빼도 됩니다. 컬럼식 뒤에 한 칸 띄고 이름을 적으면 그것이 별칭입니다. 다만 AS를 빼면 컬럼을 하나 더 적은 것인지 별칭인지 헷갈리기 쉬워, 쉼표 하나를 빠뜨리면 다른 결과가 조용히 나옵니다.
큰따옴표가 필요한 자리
별칭에 공백이나 특수문자가 들어가거나, 대소문자를 그대로 보이고 싶거나, 별칭이 숫자로 시작하면 큰따옴표로 감쌉니다.
SELECT 급여 * 12 AS "연간 급여",
급여 AS "Monthly"
FROM 사원;
작은따옴표가 아니라 큰따옴표라는 점이 문항이 됩니다. 작은따옴표는 문자 값을 감싸는 기호라 별칭 자리에 쓰면 오류가 납니다.
DISTINCT
중복을 없애는 기준
DISTINCT는 결과에서 중복된 행을 하나로 줄입니다. 위 사원 테이블에서 부서코드를 그냥 조회하면 D01이 두 번 나오지만 SELECT DISTINCT 부서코드 FROM 사원;은 D01·D02 두 행만 돌려줍니다.
컬럼을 둘 이상 적으면 그 조합 전체가 같을 때만 중복으로 칩니다. SELECT DISTINCT 부서코드, 급여 FROM 사원;은 부서코드가 같아도 급여가 다르면 따로 세므로 세 행이 그대로 나옵니다. 「DISTINCT는 첫 컬럼만 본다」는 보기가 오답으로 나옵니다.
ALL과 위치
ALL은 중복을 그대로 두라는 뜻이고 아무것도 안 적었을 때의 기본값이라 보통 생략합니다. 그리고 DISTINCT는 SELECT 바로 뒤에 한 번만 옵니다 — 컬럼마다 따로 붙일 수 없습니다.
산술 연산자
네 연산자와 우선순위
숫자에 쓰는 연산자는 +·-·*·/ 넷입니다. 우선순위는 곱셈과 나눗셈이 덧셈·뺄셈보다 앞서고, 괄호가 그보다 앞섭니다.
| 식 | 결과 | 왜 |
|---|---|---|
100 + 200 * 2 |
500 | 곱셈이 먼저다 |
(100 + 200) * 2 |
600 | 괄호가 먼저다 |
급여 * 12 + 상여 |
급여를 12배 한 뒤 상여를 더한다 | 곱셈이 먼저다 |
급여 * (12 + 상여) |
상여를 12에 더한 뒤 급여를 곱한다 | 괄호가 먼저다 |
셋째와 넷째 줄이 시험에 나오는 형태입니다. 연봉을 구한다면 상여도 열두 달 받는지 한 번 받는지에 따라 괄호 자리가 달라집니다.
날짜에 쓰는 산술
날짜에는 +와 -만 의미가 있습니다. 날짜에 숫자를 더하면 그만큼 뒤의 날짜가 되고, 날짜끼리 빼면 두 날짜 사이의 일수가 나옵니다. 날짜를 곱하거나 나누는 식은 성립하지 않습니다.
더하는 숫자의 단위는 일입니다. 입사일에 1을 더하면 다음 날이고, 30을 더하면 30일 뒤입니다. 한 달을 더하려면 달마다 일수가 달라 숫자로는 정확히 안 되므로 ADD_MONTHS 같은 함수를 씁니다. 그리고 날짜에서 날짜를 뺀 결과는 날짜가 아니라 숫자이므로, 그 값을 다시 날짜처럼 쓰면 원하는 결과가 나오지 않습니다.
NULL이 낀 산술 연산
NULL은 값이 없다는 표시이지 0이 아닙니다. 그래서 NULL이 하나라도 낀 산술 연산의 결과는 언제나 NULL입니다.
SELECT 사원명, 급여 * 12 + 상여 AS 연봉
FROM 사원;
-- 홍길동 3650
-- 김철수 NULL ← 상여가 NULL이라 전체가 NULL
-- 이영희 4900
김철수의 급여가 250이어서 3000이 나와야 할 것 같지만, 상여가 NULL이라 더하는 순간 전체가 NULL이 됩니다. 이것을 막으려면 NVL(상여, 0)처럼 NULL을 다른 값으로 바꿔 놓고 계산합니다.
SELECT 사원명, 급여 * 12 + NVL(상여, 0) AS 연봉
FROM 사원;
-- 김철수 3000
합성 연산자
문자열을 잇는 방법
합성 연산자는 값 여럿을 하나의 문자열로 이어 붙이는 연산자입니다. 세로 막대 두 개를 겹쳐 쓰고, 같은 일을 하는 CONCAT 함수도 있습니다.
SELECT 사원명 || '님' AS 호칭,
CONCAT(사원명, '님') AS 호칭2
FROM 사원;
-- 홍길동님 홍길동님
CONCAT은 인자를 둘만 받으므로 셋을 이으려면 CONCAT(CONCAT(a, b), c)처럼 겹쳐 써야 합니다. 합성 연산자는 그런 제한 없이 계속 이어 붙일 수 있어 실무에서는 이쪽을 더 씁니다.
숫자와 NULL을 이을 때
숫자 컬럼을 이어 붙이면 문자로 자동 변환되어 붙습니다. 사원명 || 급여는 홍길동300이 됩니다. 그리고 NULL을 이어 붙이면 산술 연산과 달리 전체가 NULL이 되지 않고 없는 것처럼 지나갑니다 — 사원명 || 상여는 김철수 행에서 김철수가 됩니다. 산술은 NULL에 전염되고 합성은 전염되지 않는다는 이 차이가 그대로 출제됩니다.
연습 문제
SELECT문에 대한 설명으로 옳지 않은 것은?
①*를 적으면 테이블의 모든 컬럼이 나온다
② 결과의 컬럼 순서는 테이블에 정의된 순서를 따른다
③ 예약어는 대소문자를 가리지 않는다
④ 작은따옴표로 감싼 값은 대소문자를 가린다②. 결과의 컬럼 순서는SELECT뒤에 적은 순서를 따릅니다.컬럼 별칭에 대한 설명으로 옳은 것은?
①AS는 반드시 적어야 한다
② 별칭에 공백이 들어가면 작은따옴표로 감싼다
③ 별칭이 숫자로 시작하면 큰따옴표로 감싼다
④ 별칭은 원래 컬럼 이름을 바꿔 저장한다③. 공백·특수문자·숫자 시작·대소문자 구분이 필요하면 큰따옴표를 씁니다.AS는 생략할 수 있고, 별칭은 결과에만 붙는 이름이라 테이블은 그대로입니다.아래 테이블에서 다음 SQL의 결과 행 수는?
「사원 테이블은 (홍길동, D01, 300), (김철수, D01, 250), (이영희, D02, 400) 세 행이다」SELECT DISTINCT 부서코드, 급여 FROM 사원;
① 1
② 2
③ 3
④ 4③.DISTINCT는 적은 컬럼의 조합 전체가 같을 때만 중복으로 칩니다.(D01, 300)·(D01, 250)·(D02, 400)이 모두 달라 세 행이 그대로 나옵니다.급여가 250이고상여가 NULL인 행에서급여 * 12 + 상여의 결과는?
① 3000
② 3250
③ 0
④ NULL④. 산술 연산에 NULL이 하나라도 끼면 결과는 NULL입니다. 3000을 얻으려면급여 * 12 + NVL(상여, 0)으로 씁니다.다음 두 식의 결과가 각각 얼마인가?
급여는 300,상여는 50이다.
급여 * 12 + 상여와급여 * (12 + 상여)
① 3650, 18600
② 3600, 3650
③ 3650, 3600
④ 18600, 3650①. 앞은 300 × 12 = 3600에 50을 더해 3650이고, 뒤는 12 + 50 = 62에 300을 곱해 18600입니다. 괄호 하나로 결과가 다섯 배가 됩니다.합성 연산자에 대한 설명으로 옳지 않은 것은?
① 숫자 컬럼을 이어 붙이면 문자로 변환되어 붙는다
② NULL을 이어 붙이면 결과 전체가 NULL이 된다
③CONCAT함수는 인자를 둘만 받는다
④ 합성 연산자는 여러 값을 계속 이어 붙일 수 있다②. 합성은 산술과 달라서 NULL을 없는 것처럼 지나갑니다.사원명 || 상여는 상여가 NULL이어도 사원명만 남습니다.다음 SQL의 결과로 옳은 것은? 사원명이
홍길동, 급여가 300, 상여가 NULL이다.
① A는SELECT 사원명 || '/' || 상여 AS A, 급여 + 상여 AS B FROM 사원;홍길동/, B는 NULL
② A는 NULL, B는 NULL
③ A는홍길동/, B는 300
④ A는홍길동/NULL, B는 300①. 합성은 NULL을 건너뛰어홍길동/이 되고, 산술은 NULL에 전염되어 B가 NULL이 됩니다. NULL이NULL이라는 글자로 붙지는 않습니다.DISTINCT에 대한 설명으로 옳은 것은?
① 컬럼마다 따로 붙일 수 있다
② 아무것도 적지 않으면DISTINCT가 적용된다
③SELECT바로 뒤에 한 번만 적는다
④ NULL이 여럿이면 각각 다른 값으로 세어 그대로 남는다③. 기본값은 중복을 그대로 두는ALL이고,DISTINCT는 NULL도 하나로 묶습니다.사원이 세 명인 테이블에서 다음 SQL의 결과 행 수와 첫 컬럼의 값으로 옳은 것은?
SELECT '재직' AS 구분, 입사일 + 30 AS 만료일 FROM 사원;
① 1행,재직
② 3행,재직이 세 번
③ 3행, 첫 행만재직
④ 오류가 난다②. 컬럼 자리에 적은 값은 조회된 행마다 되풀이되어 붙습니다. 날짜에 더하는 숫자의 단위는 일이므로 만료일은 입사일의 30일 뒤가 됩니다.
다음 자리에서는 조회할 행을 골라내는 WHERE 절로 들어갑니다. 여기서 본 NULL의 성질이 거기서 한 번 더 나오는데, 그때는 산술이 아니라 비교에서 문제가 됩니다 — = NULL이 왜 아무것도 못 찾는지가 다음 절의 중심입니다.

