개발자공부일기

SQL 기본 문법 본문

코딩테스트/SQL문제 풀기

SQL 기본 문법

JavaCPP 2025. 12. 31. 20:32

딱히 정리한적도 없기도하고 오랜만에 sql문제를 풀려하니 기억이 바로바로 안나서 재활겸 정리해봤습니다.

작성 순서
SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT/FETCH

 

논리적 실행 순서(DB가 처리하는 순서)

  1. FROM (JOIN 포함)
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY
  7. LIMIT/FETCH

 

예시 테이블

 

USERS

user_id name country joined
1 Min KR 2021-03-10
2 Jae KR 2022-10-05
3 Alex US 2022-10-20

 

 

PRODUCTS

product_id product_name category unit_price
10 Tshirt top 20000
20 Sneakers shoes 80000
30 Cap acc 15000

 

 

ONLINE_SALE

sale_id user_id product_id created_date qty status
1001 1 10 2022-10-01 1 PAID
1002 1 10 2022-10-02 1 PAID
1003 1 20 2022-11-01 1 CANCELLED
1004 2 10 2022-10-03 2 PAID
1005 2 30 2022-10-04 1 PAID
1006 2 30 2022-12-01 1 PAID
1007 3 10 2022-10-05 1 PAID

 

SELECT (무엇을 보여줄지)

SELECT는 결과 테이블의 “열(column) 구성”을 결정합니다.

 

기본 형태

SELECT sale_id, status
FROM ONLINE_SALE;

 

실행 결과

sale_id status
1001 PAID
1002 PAID
1003 CANCELLED
1004 PAID
1005 PAID
1006 PAID
1007 PAID

 

 별칭(alias) 붙이기

  • 컬럼/표현식에 이름을 붙여 결과를 읽기 쉽게 만듭니다.(AS 생략가능)
SELECT sale_id id, created_date AS ordered_at
FROM ONLINE_SALE;

 

실행 결과

id ordered_at
1001 2022-10-01
1002 2022-10-02
1003 2022-11-01
1004 2022-10-03
1005 2022-10-04
1006 2022-12-01
1007 2022-10-05

 

표현식/계산 컬럼

  • 단가 * 수량, 날짜 가공, 문자열 합치기 같은 “계산된 열”을 만들 수 있습니다.
SELECT sale_id, qty, qty * 1000 AS dummy_amount
FROM ONLINE_SALE;

 

실행 결과

sale_id qty dummy_amount
1001 1 1000
1002 1 1000
1003 1 1000
1004 2 2000
1005 1 1000
1006 1 1000
1007 1 1000

 

DISTINCT (중복 제거)

  • 결과에서 중복 행을 제거합니다.
SELECT DISTINCT user_id
FROM ONLINE_SALE;

 

실행 결과

user_id
1
2
3

 

주의

  • DISTINCT는 “SELECT 결과의 전체 행” 기준으로 중복 제거합니다.
  • GROUP BY와는 목적이 다릅니다(중복 제거 vs 집계).

 

FROM (어떤 데이터에서 가져올지)

FROM은 단순히 “테이블을 적는 곳”이 아니라, DB 관점에서 “작업 대상 행 집합을 만드는 단계”입니다.

실제 존재하는 테이블이 아니어도 된다는 얘기입니다. 예를 들면 JOIN으로 생성된 테이블이 있겠네요.

 

단일 테이블

SELECT *
FROM USERS;

실행 결과

 

user_id name country joined
1 Min KR 2021-03-10
2 Jae KR 2022-10-05
3 Alex US 2022-10-20

 

테이블 별칭(alias)

  • JOIN에서 거의 필수로 쓰입니다.
SELECT u.user_id, u.name
FROM USERS u;

 

실행 결과

user_id name
1 Min
2 Jae
3 Alex

 

JOIN은 FROM 단계에서 수행됩니다

  • FROM에서 테이블을 붙여서 “더 큰 행 집합”을 만들고, 그 결과에 WHERE/GROUP BY를 적용합니다.

INNER JOIN (매칭되는 것만)

SELECT s.sale_id, u.name, p.product_name, s.qty
FROM ONLINE_SALE s
JOIN USERS u ON s.user_id = u.user_id
JOIN PRODUCTS p ON s.product_id = p.product_id;

실행 결과

 

sale_id name product_name qty
1001 Min Tshirt 1
1002 Min Tshirt 1
1003 Min Sneakers 1
1004 Jae Tshirt 2
1005 Jae Cap 1
1006 Jae Cap 1
1007 Alex Tshirt 1

 

INNER JOIN외에도 다양한 JOIN이 있지만 다음에 따로 알아보도록 하고 기본적인것만 살펴봅시다.

 

 

FROM 서브쿼리(인라인 뷰)

  • FROM에서 “집계 결과”를 임시 테이블처럼 만들고, 바깥 쿼리에서 다시 필터링/정렬합니다.
SELECT x.user_id, x.cnt
FROM (
  SELECT user_id, COUNT(*) AS cnt
  FROM ONLINE_SALE
  GROUP BY user_id
) x
WHERE x.cnt >= 2;

실행 결과

 

user_id cnt
1 3
2 3

 

WHERE (행 필터링)
WHERE는 “GROUP BY 이전”에 개별 행을 걸러냅니다.

같다

SELECT sale_id, status
FROM ONLINE_SALE
WHERE status = 'PAID';

 

실행 결과

sale_id status
1001 PAID
1002 PAID
1004 PAID
1005 PAID
1006 PAID
1007 PAID

 

다르다

SELECT sale_id, status
FROM ONLINE_SALE
WHERE status <> 'CANCELLED';

실행 결과
(가상데이터에서 CANCELLED는 1003 한 건뿐이라, 위 결과와 동일하게 나옵니다.)

 

sale_id status
1001 PAID
1002 PAID
1004 PAID
1005 PAID
1006 PAID
1007 PAID

 

범위(BETWEEN)

SELECT *
FROM USERS
WHERE user_id BETWEEN 1 AND 2;

 

실행 결과

user_id name country joined
1 Min KR 2021-03-10
2 Jae KR 2022-10-05

BETWEEN은 양 끝을 포함합니다.

 

 

포함(IN) / 제외(NOT IN)

SELECT *
FROM PRODUCTS
WHERE category IN ('top', 'acc');

 

실행 결과

product_id product_name category unit_price
10 Tshirt top 20000
30 Cap acc 15000

 

 

NULL 체크
NULL은 = 비교가 안 됩니다.

  • WHERE col IS NULL
  • WHERE col IS NOT NULL

(현재 가상데이터에는 NULL 값이 없으므로, 예시로 status IS NULL을 실행하면 0행이 나옵니다.)

SELECT sale_id, status
FROM ONLINE_SALE
WHERE status IS NULL;

실행 결과: 0 rows

 

GROUP BY + 집계함수
GROUP BY는 “같은 값(또는 조합)”을 묶어서 집계할 때 씁니다.

6.1 사용자별 구매 건수

SELECT user_id, COUNT(*) AS cnt
FROM ONLINE_SALE
GROUP BY user_id;

 

실행 결과
(이 쿼리는 CANCELLED도 포함한 “주문 행 수” 기준입니다.)

user_id cnt
1 3
2 3
3 1

 

두 컬럼 조합으로 그룹화

SELECT user_id, product_id, COUNT(*) AS dup_count
FROM ONLINE_SALE
GROUP BY user_id, product_id;

 

실행 결과

user_id product_id dup_count
1 10 2
1 20 1
2 10 1
2 30 2
3 10 1

 

 

HAVING (그룹 필터링)
HAVING은 그룹화 이후 집계 결과에 조건을 겁니다.
“중복 2개 이상”은 WHERE가 아니라 HAVING입니다.

SELECT user_id, product_id, COUNT(*) AS dup_count
FROM ONLINE_SALE
GROUP BY user_id, product_id
HAVING COUNT(*) >= 2;

실행 결과

 

user_id product_id dup_count
1 10 2
2 30 2

 

 

ORDER BY (정렬)
정렬 우선순위를 여러 개 줄 수 있습니다.

ASC(default):오름차순 / DESC:내림차순

 

GROUP BY에서 보여드린 예시에 ORDER BY만 추가했습니다.

 

SELECT user_id, product_id, COUNT(*) AS dup_count
FROM ONLINE_SALE
GROUP BY user_id, product_id
ORDER BY user_id ASC, product_id DESC;

 

실행 결과
(user_id 오름차순, 같은 user_id 안에서는 product_id 내림차순)

user_id product_id dup_count
1 20 1
1 10 2
2 30 2
2 10 1
3 10 1

 

 

LIMIT/FETCH (상위 N개)

  • MySQL: LIMIT
  • 표준 SQL/일부 DB: FETCH FIRST N ROWS ONLY
SELECT *
FROM ONLINE_SALE
ORDER BY created_date
LIMIT 3;

실행 결과
(created_date 오름차순 기준 상위 3행)

 

sale_id user_id product_id created_date qty status
1001 1 10 2022-10-01 1 PAID
1002 1 10 2022-10-02 1 PAID
1004 2 10 2022-10-03 2 PAID

 

 

 

 

서브쿼리(쿼리 안의 쿼리)

11.1 WHERE + IN

SELECT user_id, name
FROM USERS
WHERE user_id IN (
  SELECT user_id
  FROM ONLINE_SALE
  GROUP BY user_id
  HAVING COUNT(*) >= 3
);

 

실행 결과
(ONLINE_SALE에서 user_id별 행 수가 3 이상인 사용자는 1, 2)

user_id name
1 Min
2 Jae

 

WHERE + EXISTS

SELECT u.user_id, u.name
FROM USERS u
WHERE EXISTS (
  SELECT 1
  FROM ONLINE_SALE s
  WHERE s.user_id = u.user_id
    AND s.status = 'CANCELLED'
);

 

실행 결과
(CANCELLED 주문이 있는 사용자는 user_id=1)

user_id name
1 Min

 

FROM 서브쿼리(인라인 뷰)

SELECT x.user_id, x.cnt
FROM (
  SELECT user_id, COUNT(*) AS cnt
  FROM ONLINE_SALE
  GROUP BY user_id
) x
WHERE x.cnt >= 2
ORDER BY x.user_id;

 

실행 결과
(cnt >= 2인 user_id는 1, 2)

user_id cnt
1 3
2 3

 

'코딩테스트 > SQL문제 풀기' 카테고리의 다른 글

문제 풀어보기  (0) 2024.12.06
SQL 문법 문제(기초) Step10  (0) 2024.10.25
SQL 문법 문제(기초) Step9  (0) 2024.10.24
SQL 문법 문제(기초) Step8  (0) 2024.10.22
SQL 문법 문제(기초) Step7  (0) 2024.10.21