PromleeBlog
sitemap
aboutMe

posting thumbnail
SQL 조회 문법 총정리 2편 (MySQL/Oracle)
Advanced SQL Query Syntax (MySQL/Oracle)

📅

🚀

들어가기 전에 🔗

지난
SQL 조회 문법 총정리 1편
에서는 기본적인 SELECT, WHERE, GROUP BY, JOIN 등의 핵심 명령어를 알아보았습니다.
오늘은 여기서 한 단계 더 나아가, 코딩 테스트에서 더욱 복잡하고 까다로운 문제를 해결하는 데 도움이 될
SQL 조회 심화 문법
들을, 특히
MySQL과 Oracle 사용자분들
에게 맞춰 살펴보려고 합니다.

지난 시간 복습 및 예제 테이블 🔗

1편에서 사용했던 Users 테이블과 Orders 테이블을 다시 한번 떠올려보겠습니다.
이 테이블들을 기반으로 심화된 예제들을 살펴볼 예정입니다.
(Orders 테이블에 order_dateamount 컬럼을 추가하고, Users 테이블에도 데이터를 추가했습니다.)

🚀

문자열 다루기: CONCAT, SUBSTRING, LENGTH 등 🔗

데이터베이스에는 텍스트 형태의 데이터가 많이 저장됩니다.
이러한 문자열 데이터를 효과적으로 조작하고 분석하기 위한 함수들을 알아봅시다.
MySQL과 Oracle은 유사한 기능을 제공하지만 함수명이나 사용법에 약간의 차이가 있을 수 있습니다.

문자열 합치기: CONCAT, || 🔗

여러 문자열을 하나로 합칠 때 사용합니다.
CONCAT(문자열1, 문자열2, ...)는 NULL을 무시하고 합칩니다. ||는 NULL이 포함되면 결과도 NULL이 됩니다.

예시
이름과 이메일을 합쳐서 '이름 (이메일)' 형태로 출력*
user_profile
홍길동 (hong@example.com)
이동훈 (donghoon099@naver.com)
햄랑이 (hamlang@ham.ham)
홍길은 (이메일 없음)
제임스 (james@example.com)
이몽룡 (mong@another.com)

문자열 자르기 🔗

문자열의 특정 부분만 잘라낼 때 사용합니다.

예시
이메일 주소에서 아이디 부분만 추출하기 (@ 앞부분)
emailemail_id
hong@example.comhong
donghoon099@naver.comdonghoon099
hamlang@ham.hamhamlang
james@example.comjames
mong@another.commong

문자열 길이 🔗

문자열의 길이를 반환합니다.

예시
이름이 3글자인 사용자 찾기 (문자 기준)
namename_length
홍길동3
이동훈3
햄랑이3
제임스3
이몽룡3

문자열 치환 🔗

문자열 내의 특정 부분을 다른 문자열로 바꿀 때 사용합니다.

예시
이메일 도메인 '.com'을 '.net'으로 변경하기
-- MySQL & Oracle 동일
SELECT email, REPLACE(email, '.com', '.net') AS new_email FROM Users WHERE email LIKE '%.com';
emailnew_email
hong@example.comhong@example.net
james@example.comjames@example.net

대소문자 변경 🔗

문자열을 모두 대문자 또는 소문자로 변경합니다.

예시
이름을 모두 대문자로 출력
-- MySQL & Oracle 동일
SELECT name, UPPER(name) AS upper_name FROM Users;
nameupper_name
jamesJAMES
... (한글은 변화 없음)

🚀

더 복잡한 JOIN 활용 🔗

JOIN은 대부분의 경우 SQL 표준을 따르므로 MySQL과 Oracle에서 사용법이 거의 동일합니다.

RIGHT JOIN 및 FULL OUTER JOIN 🔗


예시
Orders 테이블 기준으로 모든 주문과 해당 주문자 이름 표시 (주문자가 없는 주문도 포함)
SELECT U.name, O.product, O.order_date
FROM Users U
RIGHT JOIN Orders O ON U.id = O.user_id;
nameproductorder_date
홍길동Apple2023-01-15
.........
Kiwi2023-03-12

SELF JOIN - 자체 조인 🔗


예시
각 직원의 이름과 그 직원의 매니저 이름 출력하기
SELECT e1.name AS employee_name, e2.name AS manager_name
FROM Employees e1
LEFT JOIN Employees e2 ON e1.manager_id = e2.id;
employee_namemanager_name
Alice
BobAlice
CharlieAlice
DavidBob

여러 조건을 사용하는 JOIN 🔗

MySQL과 Oracle 모두 ON 절에 여러 조건을 사용할 수 있습니다.

예시
Users와 Orders를 조인하되, 특정 사용자(예: 홍길동)의 특정 상품(예: Apple) 주문만 가져오기
SELECT U.name, O.product
FROM Users U
INNER JOIN Orders O ON U.id = O.user_id
WHERE U.name = '홍길동' AND O.product = 'Apple';
nameproduct
홍길동Apple
홍길동Apple

🚀

정렬 및 다른 구조의 SELECT 결과 합치기 🔗

UNIONUNION ALL도 SQL 표준으로, MySQL과 Oracle에서 동일하게 동작합니다.

UNION 결과 정렬하기 🔗


예시
(SELECT name FROM Users)
UNION
(SELECT name FROM Employees) -- 1편의 Employees 테이블 예시
ORDER BY name ASC;
name
김철수
... (정렬된 결과)

컬럼 개수 및 타입 일치시키기 🔗

타입 변환 시 함수명이 다를 수 있습니다.

예시
Users 테이블의 이름(문자열)과 Orders 테이블의 주문 수량(숫자)을 합쳐서 보기
itemtype
홍길동User
......
3000Order Amount
......

🚀

윈도우 함수 (Window Functions) 🔗

윈도우 함수는 SQL에서 특정 행을 기준으로 계산을 수행할 수 있습니다.
사용법은 함수 명과 괄호로 시작하며, OVER() 절을 사용하여 윈도우를 정의합니다.
Window
Window

기본 구조 및 주요 순위 함수 🔗

ROW_NUMBER(), RANK(), DENSE_RANK()는 MySQL과 Oracle 모두 동일하게 사용합니다.
ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...)
RANK() OVER (PARTITION BY ... ORDER BY ...)
DENSE_RANK() OVER (PARTITION BY ... ORDER BY ...)

예시
사용자(Users)를 나이(age)가 많은 순으로 순위 매기기
SELECT
    name,
    age,
    ROW_NUMBER() OVER (ORDER BY age DESC) AS row_num,
    RANK() OVER (ORDER BY age DESC) AS rnk,
    DENSE_RANK() OVER (ORDER BY age DESC) AS dense_rnk
FROM Users;
nameagerow_numrnkdense_rnk
제임스30111
이동훈27222
...

집계 함수와 함께 사용 🔗

SUM() OVER (...), AVG() OVER (...) 등도 MySQL과 Oracle에서 동일하게 사용합니다.
이 함수들은 특정 그룹 내에서 집계된 값을 계산할 수 있습니다.

예시
각 사용자의 주문(Orders)에 대해, 해당 사용자의 총 주문 금액과 함께 각 주문 정보 표시
SELECT
    O.id AS order_id,
    U.name AS user_name,
    O.product,
    O.amount,
    SUM(O.amount) OVER (PARTITION BY U.id) AS user_total_amount
FROM Orders O
JOIN Users U ON O.user_id = U.id
ORDER BY U.name, O.id;
order_iduser_nameproductamountuser_total_amount
1홍길동Apple300013000
3홍길동Orange200013000
6홍길동Apple300013000
10홍길동Strawberry800013000
2이동훈Banana15006500
7이동훈Grape50006500
5홍길은Watermelon70007000
...

LAG() / LEAD() 🔗

LAG()LEAD() 함수도 MySQL과 Oracle에서 동일하게 사용합니다.
이 함수들은 현재 행을 기준으로 이전 또는 이후의 행 값을 가져오는 데 사용됩니다.

예시
각 주문에 대해, 해당 사용자의 바로 이전 주문일 가져오기
SELECT
    O.id AS order_id,
    U.name AS user_name,
    O.order_date,
    LAG(O.order_date, 1, NULL) OVER (PARTITION BY U.id ORDER BY O.order_date) AS previous_order_date
FROM Orders O
JOIN Users U ON O.user_id = U.id
ORDER BY U.name, O.order_date;
order_iduser_nameorder_dateprevious_order_date
1홍길동2023-01-15NULL
3홍길동2023-01-172023-01-15
6홍길동2023-02-102023-01-17
...

🚀

날짜 및 시간 함수 다루기 🔗

날짜/시간 함수는 DBMS별 차이가 큰 부분 중 하나입니다.

현재 날짜/시간 얻기 🔗

날짜/시간 형식 변환 🔗

날짜/시간 부분 추출 🔗


예시
각 주문이 일어난 연도, 월, 요일 이름 추출하기
order_dateorder_yearorder_monthorder_dayname
2023-01-1520231Sunday
............

날짜/시간 연산 🔗


예시
주문일로부터 7일 후 날짜 계산하기
order_dateafter_7_days
2023-01-152023-01-22
......

참고 🔗