
SQL Syntax 정리 - SELECT 구문
- 이번 포스팅에서는 DML(Data Manufulation Language) 중 하나인 SELECT 구문의 문법에 대해 알아보겠습니다.
- SELECT 문의 문법 구조와 제공되는 함수를 이해한다면 데이터베이스에서 필요한 정보를 원하는 형태로 조회할 수 있습니다.
- 예시의 쿼리는 MYSQL 문법을 기준으로 작성되었습니다.
쿼리의 구조
SELECT 컬럼명 FROM 테이블명 WHERE 조건식 GROUP BY 컬럼명 HAVING 조건식 ORDER BY 컬럼명
SELECT 쿼리는 일반적으로 위와 같은 구조로 작성됩니다. 각 명령어의 역할은 다음과 같습니다.
- SELECT :추출된 데이터들을 조회
- FROM : 조회하고자 하는 테이블을 지정
- WHERE : 테이블에서 WHERE절에서 주어진 조건에 맞는 데이터를 추출
- GROUP BY : 데이터들끼리 묶어 구룹으로 만들어주는 구문
- HAVING : GROUP BY에서 묶어준 그룹 중 주어진 조건에 맞는 그룹을 추출
- ORDER BY : 추출된 데이터들을 정렬
실행 순서
쿼리를 작성하는 순서와 다르게 쿼리를 실행할 경우에는 다음과 같은 순서로 실행됩니다.
(1) FROM -> (2) WHERE -> (3) GROUP BY -> (4) HAVING -> (5) SELECT -> (6) ORDER BY
쿼리의 실행순서를 잘 이해하고 있다면 쿼리를 설계할 때 큰 도움이 됩니다.
✅ (ex : SELECT 에서 만들어진 alias 는 ORDER BY 구문에서만 사용가능, SELECT 다음으로 오는 구문은 ORDER BY 뿐이기 때문)
Syntax 설명 및 실습
- 각 구문에 대해 SQL 문제와 정답 쿼리를 예시로 설명하도록 하겠습니다.
SELECT
- 조회를 하길 원하는 컬럼을 지정해서 선택할 수 있는 구문.
- *(astrick)을 사용해서 FROM 구문에서 선택한 테이블의 모든 컬럼을 지정할 수 있다.
- DISTINCT 구문을 사용해 중복되는 컬럼값을 가지는 레코드의 중복을 제거하고 하나의 레코드만 출력할 수 있도록 지정한다.
- 집계 함수[COUNT(),MAX(),MIN(),SUM(),AVG()]를 사용해서 GROUP BY 에서 지정된 컬럼의 통계량을 조회할 수 있다.
-> (GROUP BY 예시에서 확인) - IF, CASE 등의 구문으로 특정 레코드 값을 다른 값으로 변경해서 출력할 수 있다.
- [IF, IFNULL, ISNULL, CASE WHEN, NVL]
# * 를 통해 모든 컬럼을 조회하는 쿼리
SELECT * FROM ANIMAL_INS
ORDER BY ANIMAL_ID
# DISTINCT 구문을 사용해서 중복되는 컬럼값을 가지는 레코드를 하나의 레코드로 출력하는 쿼리
SELECT COUNT(DISTINCT NAME)
FROM ANIMAL_INS;
[Programmers] 12세 이하의 여자 환자 목록 출력하기
# SELECT 문에 조건을 걸어 특정 조건의 값을 원하는 값으로 바꾸는 쿼리
SELECT PT_NAME, PT_NO,GEND_CD, AGE, IFNULL(TLNO,'NONE') AS TLNO
FROM PATIENT
WHERE GEND_CD = 'W'
AND AGE <= 12
ORDER BY AGE DESC, PT_NAME;
[Programmers] 조건별로 분류하여 주문상태 출력하기
SELECT ORDER_ID,
PRODUCT_ID,
DATE_FORMAT(OUT_DATE, "%Y-%m-%d") AS OUT_DATE,
(
CASE
WHEN OUT_DATE <= "2022-05-01 00:00:00" THEN "출고완료"
WHEN OUT_DATE > "2022-05-01 00:00:00" THEN "출고대기"
ELSE "출고미정"
END
) AS '출고여부'
FROM FOOD_ORDER
ORDER BY ORDER_ID
WHERE
- WHERE 절은 특정 컬럼의 조건에 맞는 레코드를 조회하기 위해 사용되는 구문입니다.
- 다음과 같은 연산자를 사용해서 조건문을 제어할 수 있습니다.
[= , >, <, >= , <=, <>(!=), BETWEEN, LIKE, IN] - 복합연산자를 사용해서 조회조건을 보다 정교하게 만들 수 있습니다.
- [AND, OR, NOT]
- OR 연산자보다 UNION ALL을 사용해 보다 효율적인 쿼리를 작성할 수 있습니다.
# WHERE 절에서 연산자의 활용 예시
# BETWEEN 과 AND 조건을 조합해서 조건에 레코드의 수를 출력하는 쿼리
SELECT COUNT(*) AS USERS
FROM USER_INFO
WHERE AGE BETWEEN 0 AND 29 #복합연산자 AND를 사용하는 WHERE 절
AND YEAR(JOINED) = 2021; #BETWEEN, = 를 사용하는 WHERE 절
[Programmers] 강원도에 위치한 생산공장 목록 출력하기
# LIKE 구문을 사용해서 특정 문자열과 매칭되는 레코드를 출력하는 쿼리
SELECT FACTORY_ID, FACTORY_NAME, ADDRESS
FROM FOOD_FACTORY
WHERE ADDRESS LIKE "강원도%"
ORDER BY FACTORY_ID
GROUP BY
[Programmers] 진료과별 총 예약 횟수 출력하기
SELECT MCDP_CD AS "진료과코드",
COUNT(MCDP_CD) AS '진료과건수'
FROM APPOINTMENT
WHERE APNT_YMD LIKE "2022-05%"
GROUP BY MCDP_CD
ORDER BY COUNT(MCDP_CD), MCDP_CD
SELECT (
CASE
WHEN PRICE < 10000 THEN 0
ELSE TRUNCATE(PRICE, -4)
END
) AS PRICE_GROUP , COUNT(PRODUCT_ID)
FROM PRODUCT
GROUP BY PRICE_GROUP
ORDER BY PRICE_GROUP;
✅ 쿼리의 실행 순서에 따라 SELECT에서 선언된 PRICE_GROUP alias는 GROUP BY 구문에서 참조할 수 없습니다. 위같은 쿼리가 어떻게 가능할까요?
👀 MySQL과 Postgre에서는 SELECT 구문에서 정의 된 alias를 다른 구문에서 인식할 수 있는 기능을 제공합니다. 그렇기 때문에 아래와 같은 쿼리가 가능합니다. 반면, Oracle과 같은 DBMS 에서는 해당 기능을 제공하지 않습니다.
HAVING
- group by에서 사용하는 조건문 그룹화 된 레코드 중 HAVING 절의 조건에 맞는 레코드를 찾을 수 있습니다.
- 집계함수에 대한 조건을 걸 수 있습니다.
SELECT HOUR(DATETIME) AS HOUR,
COUNT(HOUR(DATETIME)) AS Count
FROM ANIMAL_OUTS
GROUP BY HOUR
HAVING HOUR >= 9
AND HOUR <= 19
ORDER BY HOUR ASC;
[Programmers] 우유와 요거트가 담긴 장바구니
SELECT A.CART_ID
FROM CART_PRODUCTS AS A
WHERE A.NAME IN ("Milk", "Yogurt")
GROUP BY A.CART_ID
HAVING COUNT(DISTINCT A.NAME) >= 2
ORDER BY A.CART_ID;
ORDER BY
- 특정 컬럼값을 기준으로 오름차순, 내림차순 출력을 제어한다
- [ASC, DESE]
- ASC 는 생략 가능
- 여러 컬럼을 기준으로 ORDER BY를 하게될 경우 앞서 등장한 컬럼을 기준으로 정렬 후 그 다음 컬럼내용을 정렬
- SELECT 문에서 정렬할 컬럼이 없어도 지정 가능
SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION <> 'Aged'
ORDER BY ANIMAL_ID
JOIN
- JOIN 구문을 통해 두개의 테이블을 연결하여 하나의 테이블 처럼 사용할 수 있습니다.
- INNER JOIN, OUTER JOIN, FULL JOIN 등 여러 종류의 JOIN이 있고 각각의 구문이 테이블을 연결하는 방식을 숙지하는 것이 좋습니다.
- 다음 그림을 통해 직관적으로 JOIN 구문을 통해 얻고자 하는 테이블의 결과를 알 수 있습니다.

SELECT A.ANIMAL_ID, A.NAME
FROM ANIMAL_INS AS A
JOIN ANIMAL_OUTS AS B
ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.DATETIME > B.DATETIME
ORDER BY A.DATETIME ASC;
-- 두 테이블을 OUTER JOIN을 통해 연결해서 쿼리를 작성
SELECT B.ANIMAL_ID, B.NAME
FROM ANIMAL_INS AS A
RIGHT OUTER JOIN ANIMAL_OUTS AS B
ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.ANIMAL_ID IS NULL
SELECT i.animal_id, i.animal_type, i.name
FROM animal_ins AS i
LEFT JOIN animal_outs AS o
ON i.animal_id = o.animal_id
WHERE i.sex_upon_intake != o.sex_upon_outcome
서브쿼리
- 쿼리 내부에서 작성된 또 다른 쿼리문을 의미한다.
- 쿼리 내부에서 ()로 묶여 표현된다
- 단일 행 또는 복수 행 비교 연산자와 함께 사용이 가능하다
- 서브쿼리에서는 ORDER BY 구문을 사용할 수 없다
- 서브쿼리는 다음 구문내에서 사용할 수 있다.
- SELECT
- FROM
- WHERE
- HAVING
- ORDER BY
- INSERT문의 VALUES 부분 대체
- UPDATE문의 SET 부분 대체
- 서브쿼리는 또 다시 다른 서브쿼리 안에 포함될 수 있다.
[Programmers] 즐겨찾기가 가장 많은 식당 정보 출력하기
SELECT A.FOOD_TYPE,
A.REST_ID,
A.REST_NAME,
A.FAVORITES
FROM REST_INFO AS A JOIN (
-- 서브쿼리를 사용해 가상테이블을 만드는 로직
SELECT FOOD_TYPE, MAX(FAVORITES) AS FAVORITES
FROM REST_INFO
GROUP BY FOOD_TYPE
) B
ON A.FOOD_TYPE = B.FOOD_TYPE AND A.FAVORITES = B.FAVORITES
ORDER BY FOOD_TYPE DESC
[참고]
https://yoongeons.com/entry/SQL-문법-정리
https://velog.io/@ynjch97/SQL-효율적인-SQL-쿼리-튜닝-방법
https://donghak-dev.tistory.com/156
https://kimsoungryoul.tistory.com/55
'Computer Science > Database' 카테고리의 다른 글
[DB] JPA(Java Persistence API) 란 무엇인가? (0) | 2022.12.21 |
---|---|
[DB] 정규화(Normalization)에 대해서 (0) | 2022.12.20 |