본문 바로가기

공부일지 #16 | MySQL: ORDER BY, 서브쿼리, JOIN 개념 및 사용 이유

@studying:)2025. 8. 5. 18:58

학습 날짜: 2025.08.04


오늘은 SQL에서 자주 사용되는 ORDER BY, 서브쿼리(Subquery), JOIN에 대해 배우고 실습해보았다. UNION은 실습 없이 개념만 학습하였으며, 주요 내용을 간략히 정리하였다.
또한 학습한 내용을 정리하는 과정에서, 왜 데이터를 나눠서 저장하는지, 그리고 왜 다시 JOIN이나 서브쿼리로 합쳐야 하는지에 대해서도 함께 정리해보았다.

 

 

ORDER BY 절

  • ORDER BY는 데이터를 정렬(Sorting) 할 때 사용하는 절이다.
  • 정렬 기준으로는 다음 중 하나를 사용할 수 있다:
    • 열(column) 이름
    • 열에 부여한 별칭(alias)
    • SELECT 절에서의 열 순서(숫자)
  • 정렬 방식은 다음과 같다:
    • 오름차순(Ascending): ASC (기본값)
    • 내림차순(Descending): DESC
select *
from employee_info
order by salary DESC, join_date ASC; -- salary 값이 동일할 경우, join_date로 오름차순

select employee_id,
	employee_name,
    join_date as join_dt,
    salary
from employee_info
order by 4 desc, 3 asc; 
-- 칼럼조회순서(숫자값)으로도 작성 가능 
-- & 별칭명으로도 가능(= salary desc, join_dt asc), 섞어서도 가능

 

 

서브쿼리

  • 서브쿼리는 쿼리문 안에 포함된 또 다른 쿼리문을 의미한다.
  • 소괄호 () 로 감싸서 사용하며, 메인 쿼리의 조건이나 결과 생성에 활용된다.
  • 작성 위치에 따라 다음과 같이 나뉜다:
    • SELECT절: 계산된 값 또는 통계를 함께 조회할 때 사용
    • FROM절: 서브쿼리 결과를 하나의 테이블처럼 사용할 때 사용
    • WHERE절: 조건 비교를 위해 사용 (예: 특정 값보다 크거나 포함 여부 판단 등)

 

-- select절 서브쿼리
select *, 
	(select category_name 
    	from category_info 
        where category_id = p.category_id) as category_name -- as 별칭 없으면 수식이 칼럼명 됨...
from product_info p;

-- from절 서브쿼리
select *
from (
	select category_id, 
		count(product_id) as count_of_product
	from product_info
    	group by category_id
) p -- (서브쿼리) 테이블의 별칭. SQL 문법상 필수
where count_of_product >=5;

-- where절 서브쿼리
select *
from product_info
where category_id = (select category_id
		    from category_info
                    where category_name = '가전제품');

 

 

JOIN

  • JOIN은 두 개 이상의 테이블을 결합할 때 사용한다.
  • 열(column) 단위가 아닌, 테이블 전체가 와서 결합한다.
  • 결합 기준은 ON 키워드를 사용해 명시하며, 보통 공통된 열(예: id) 을 기준으로 설정한다.
  • 종류:
    • INNER JOIN: 양쪽 테이블에 모두 존재하는 행만 조회 (가장 일반적, 기본값)
    • LEFT JOIN: 왼쪽 테이블은 모두, 오른쪽은 일치하는 것만
    • RIGHT JOIN: 오른쪽 테이블은 모두, 왼쪽은 일치하는 것만
    • OUTER JOIN: 양쪽 테이블의 모든 데이터를 포함
      → 단, MySQL에서는 직접 지원하지 않기 때문에 LEFT JOINRIGHT JOIN의 결과를 UNION 하여 구현한다.
-- left join
select *
from tableA A
left
join TableB B
on A.ID = B.ID;

-- right join
select *
from tableA A
right
join TableB B
on A.ID = B.ID;

-- inner join
select *
from tableA A
inner
join TableB B
on A.ID = B.ID;

-- outer: MySQL에서는 지원안함. left join union right join 이런 식으로 해야 함.
SELECT *
FROM tableA A
LEFT JOIN TableB B ON A.id = B.id
UNION
SELECT *
FROM tableA A
RIGHT JOIN TableB B ON A.id = B.id;

 

UNION

  • UNION은 둘 이상의 테이블을 단일 테이블로 통합하기 위해 사용된다.
  • 칼럼의 개수, 순서, 데이터 타입이 일치해야 하며, 각 열의 이름도 동일해야 오류 없이 작동한다.
  • 기본적으로 결과에서 중복된 행은 자동으로 제거된다.
  • 옵션:
    • UNION: 중복된 행을 제거한 후 결과를 반환
    • UNION ALL: 중복을 제거하지 않고 모든 결과를 그대로 출력
  • CONCAT과의 차이
    • CONCAT은 문자열을 연결하는 함수이며, 수직 결합뿐 아니라 수평 결합(열 결합) 도 가능하다.
    • 실무에서는 테이블을 붙이기보다는, 문자열을 조작하는 목적으로 CONCAT을 더 자주 사용한다.

 

테이블을 나누는 이유, 그리고 다시 합치는 이유

◈ 데이터를 ‘나눠서 저장’하는 이유 (정규화)

SQL에서 데이터를 다룰 때는 한 테이블에 전부 몰아넣지 않고, 목적에 따라 나눠서 저장합니다. 이걸 정규화(normalization)라고 한다.


WHY 왜 나눌까?

예를 들어, "고객이 어떤 제품을 주문했는지" 저장한다고 할 때, 한 테이블에 고객 정보와 주문 정보를 전부 다 적으면:

이름 주소 전화번호 주문일 주문금액
김민준 서울 010-1234 8/1 10,000
김민준 서울 010-1234 8/2 15,000
김민준 서울 010-1234 8/3 20,000


→ 이건 고객 정보가 계속 반복된다.

→ 전화번호가 바뀌면 세 줄 다 수정해야 한다.


HOW 그래서 어떻게 나누나?

  • 고객 정보는 customers 테이블에
  • 주문 내역은 orders 테이블에

이렇게 나눠서 저장하면:

  • 고객 정보는 한 번만 저장하면 되고
  • 주문 정보는 고객 ID로만 연결해 놓으면 된다
    → 이걸 나눠서 저장하는 이유는 중복을 줄이고, 관리하기 쉽게 하기 위해서이다.

🔗 그런데 분석하려면 '다시 합쳐야' 함!

이제 우리가 보고 싶은 건 뭐냐면?

"김민준이 총 몇 번 주문했지?"

"서울 사는 고객 중에서 3번 이상 주문한 사람은 누구지?"


→ 이렇게 나눠둔 테이블을 다시 ‘합쳐서’ 계산해야 된다.


그럴 때 쓰는 게 바로 JOIN과 서브쿼리!

1️⃣ JOIN을 쓰는 이유

 “테이블을 옆으로 붙여서 합치는 것”

  • 서로 다른 테이블의 연결된 데이터를 나란히 보여줄 때 사용한다.
  • 기준이 되는 컬럼(예: customer_id)을 이용해 행(row)들을 연결한다.

예: 고객 이름과 주문 금액을 함께 보고 싶을 때

SELECT c.name, o.amount
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id;


→ 고객 테이블과 주문 테이블을 연결해서

→ 고객 이름 + 주문 금액을 함께 볼 수 있다.


2️⃣ 서브쿼리(Subquery)를 쓰는 이유

 “쿼리 안에서 계산한 값을 다시 사용하고 싶을 때”

  • 어떤 값을 미리 계산해서 그 결과를 다른 쿼리에서 조건이나 출력에 사용할 수 있다.

예: "주문한 고객 중 서울에 사는 사람"

SELECT name
FROM customers
WHERE city = '서울'
  AND customer_id IN (
    SELECT customer_id
    FROM orders
  );


→ 괄호 안의 SELECT가 먼저 실행돼서

→ 그 결과(주문한 고객 ID들)를 기준으로 외부 쿼리가 작동한다.


JOIN vs 서브쿼리 차이 요약

항목 JOIN 서브쿼리
구조 테이블을 옆으로 합침 (가로로) 계산한 결과를 안쪽에서 먼저 구함
주로 사용하는 곳 두 개 이상 테이블을 나란히 비교 조건절(WHERE), 계산용 SELECT
장점 확장성 좋고 성능 좋음 복잡한 조건을 나눠 쓸 수 있어 가독성 좋음
단점 구조가 복잡해질 수 있음 반복 실행 시 성능 저하 가능

결론

  • 데이터를 나눠서 저장하는 이유는 중복을 줄이고, 관리 효율을 높이기 위해서
  • 하지만 분석할 때는 다시 합쳐야 하므로
    • JOIN을 사용해 테이블을 연결하고
    • 서브쿼리를 사용해 계산된 값이나 조건을 재사용
  • 두 방법은 상황에 따라 적절히 선택해서 써야 한다.
studying:)
@studying:) :: what i studied

studying:) 님의 학습 여정을 기록하는 블로그입니다.

목차