oracle_db_tutorial/example/01_beginner_basic_sql.md at main · voidmain443/oracle_db_tutorial · GitHub
Skip to content

Latest commit

 

History

History
219 lines (178 loc) · 14.1 KB

File metadata and controls

219 lines (178 loc) · 14.1 KB

01. Beginner Basic SQL (기본 조회 및 필터링)

📖 비즈니스 시나리오 (Business Scenario)

당신은 급성장하고 있는 글로벌 이커머스 기업 **'Orbit(오빗)'**에 갓 입사한 데이터 분석가입니다. 입사 직후, 회사는 연말 최대 할인 행사인 '블랙 프라이데이' 준비로 매우 분주합니다. 경영진을 비롯하여 마케팅팀, CS(고객 서비스)팀, 영업팀 등 다양한 부서에서 당장 캠페인 기획과 운영에 필요한 기초 데이터들을 추출해 달라는 요청이 쏟아지고 있습니다.

아직 복잡한 데이터 가공보다는, 정확한 타겟을 필터링(WHERE)하고 정돈되게 나열(ORDER BY)하여 각 부서에 빠르게 전달하는 것이 당신의 첫 번째 미션입니다. 자, 이제 각 부서의 실무 요청을 바탕으로 SQL을 작성해 봅시다!


🎯 실무 요청 사항 (Questions)

Part 1. 경영지원팀의 기초 데이터 파악 요청

경영지원팀은 회사의 전반적인 규모와 파트너사 현황을 한눈에 파악하기 위해 전체 명단 조회를 요청했습니다.

  1. [전체 고객 명단] "우리 쇼핑몰에 가입한 전체 고객 규모를 눈으로 직접 확인하고 싶습니다. customers 테이블의 모든 데이터를 추출해 주세요."
  2. [전체 상품 목록] "현재 판매를 위해 시스템에 등록된 전체 상품이 무엇무엇인지 알아야 합니다. products 테이블의 모든 데이터를 추출해 주세요."
  3. [공급업체 연락처 추출] "연말 행사를 맞아 파트너사들에게 안내 메일을 돌려야 합니다. suppliers 테이블에서 업체의 이름(name)과 담당자 이메일(contact_email) 컬럼만 뽑아주세요."
  4. [카테고리 종류 파악] "우리 쇼핑몰에 상품이 등록된 카테고리는 총 몇 종류나 되나요? products 테이블을 조회하여, 중복을 제거한 고유한 카테고리 ID(category_id) 목록을 뽑아주세요."

Part 2. 마케팅팀의 타겟 고객 필터링 (WHERE 절 활용)

마케팅팀은 한정된 예산으로 최대의 효율을 내기 위해 특정 조건에 맞는 고객과 상품을 타겟팅하려고 합니다.

  1. [특정 등급 고객] "VIP 고객들을 위한 프라이빗 파티를 기획 중입니다. customers 테이블에서 등급(grade)이 'VIP'인 고객의 이름과 이메일을 찾아주세요."
  2. [날짜 기반 신규 고객] "올해 신규 가입자 웰컴 이벤트를 하려고 합니다. customers 테이블에서 가입일(join_date)이 '2023년 1월 1일' 이후(해당일 포함)인 고객의 모든 정보를 추출하세요."
  3. [특정 가격대 상품 기획전] "1만 원에서 5만 원 사이의 중저가 선물 기획전을 준비 중입니다. product_prices 테이블에서 가격(price)이 10,000원 이상, 50,000원 이하인 상품 ID와 가격을 추출해 주세요. (BETWEEN 사용)"
  4. [할인 상품 제외] "가격이 100,000원 초과인 프리미엄 상품만 따로 마케팅하려고 합니다. product_prices 테이블에서 가격이 100,000원을 초과하는 상품 ID와 가격을 찾아주세요."
  5. [특정 키워드 검색 1] "최근 '김'씨 성을 가진 고객들을 대상으로 한 재미있는 이벤트를 구상 중입니다. customers 테이블에서 이름(name)이 '김'으로 시작하는 고객들을 모두 찾아주세요. (LIKE 사용)"
  6. [특정 키워드 검색 2] "메일 서버 오류로 '@gmail.com' 주소를 사용하는 고객들에게만 메일이 발송되지 않았습니다. 이메일 주소가 '@gmail.com'으로 끝나는 고객 정보만 추출해 주세요."
  7. [다중 조건 필터링] "영업부와 마케팅부 소속 직원들에게만 사내 공지를 돌리려 합니다. staff 테이블에서 부서(department)가 'Sales' 이거나 'Marketing'인 직원의 이름과 부서를 조회하세요. (IN 사용)"
  8. [복합 조건 필터링] "전자기기 기획전을 위해, 카테고리 ID(category_id)가 2번이면서 납품업체 ID(supplier_id)가 3번인 상품의 목록이 필요합니다. products 테이블에서 두 조건을 모두 만족하는 상품을 찾아주세요."

Part 3. CS(고객만족)팀 및 운영팀의 데이터 점검

운영팀은 데이터 누락이나 오류를 찾아내어 시스템을 정비하려고 합니다.

  1. [데이터 누락 확인 1] "회원 가입 시 등급 부여가 누락된 고객이 있는지 확인해야 합니다. customers 테이블에서 등급(grade) 값이 비어있는(NULL) 고객의 전체 정보를 찾아주세요."
  2. [데이터 누락 확인 2] "협력사 비상 연락망을 만들고 있는데, 담당자 전화번호가 없는 곳이 있습니다. suppliers 테이블에서 전화번호(phone)가 없는(NULL) 업체의 이름을 찾아주세요."
  3. [데이터 누락 제외] "전화번호가 제대로 등록된 협력사들에게만 SMS를 발송하려고 합니다. suppliers 테이블에서 전화번호가 존재하는(NOT NULL) 업체의 정보를 추출하세요."
  4. [부정 조건 검색] "배송 지연 문제가 있는 1번 공급업체를 제외하고 나머지 업체의 상품들만 급하게 메인 페이지에 노출하려 합니다. products 테이블에서 공급업체 ID(supplier_id)가 1번이 아닌 상품들을 조회하세요."

Part 4. 영업팀의 데이터 정렬 및 리포팅 (ORDER BY)

영업팀은 추출된 데이터를 보기 좋게 정렬하여 보고서를 작성하려고 합니다.

  1. [기본 오름차순 정렬] "전체 상품 목록을 가나다순으로 확인하고 싶습니다. products 테이블의 모든 데이터를 상품명(name) 기준 오름차순으로 정렬하여 조회하세요."
  2. [기본 내림차순 정렬] "가장 최근에 가입한 고객부터 순서대로 컨택을 진행하려 합니다. customers 테이블의 정보를 가입일(join_date) 기준 내림차순으로 정렬해 주세요."
  3. [다중 정렬] "고객 목록을 가입일 순으로 최신 가입자가 먼저 오게 정렬하되, 만약 같은 날에 가입한 고객들이 있다면 그 안에서는 이름의 가나다순으로 한 번 더 정렬해 주세요."
  4. [조건부 정렬 결합] "리뷰(reviews) 테이블에서 평점(rating)이 4점 이상인 긍정적인 리뷰들만 모아서, 가장 최근에 작성된 리뷰(created_at)부터 내림차순으로 볼 수 있게 리포트를 뽑아주세요."







💡 정답 및 해설 (Answers)

Tip

쿼리가 이렇게 동작하는지에 대한 원리를 이해하는 것이 중요합니다. 아래 해설을 통해 데이터베이스 엔진이 내부적으로 데이터를 어떻게 걸러내는지 원리를 파악해 보세요.

Part 1. 경영지원팀의 기초 데이터 파악 요청

1. 전체 고객 명단

SELECT * 
FROM customers;
  • 동작 원리: SELECT는 '무엇을 볼 것인가', FROM은 '어디서 가져올 것인가'를 지정합니다. *(애스터리스크)는 해당 테이블이 가진 모든 컬럼을 가져오라는 의미입니다. DB 엔진은 customers 테이블의 첫 번째 행부터 마지막 행까지 순차적으로(또는 인덱스를 통해) 스캔하며 모든 열의 데이터를 반환합니다.

2. 전체 상품 목록

SELECT * 
FROM products;

3. 공급업체 연락처 추출

SELECT name, contact_email 
FROM suppliers;
  • 동작 원리: * 대신 특정 컬럼명을 명시하면, 테이블의 여러 정보 중 지정한 열(Column)의 데이터만 잘라내어(Projection) 메모리에 올린 후 사용자에게 보여줍니다. 이는 네트워크 대역폭과 메모리를 절약하는 실무의 기본 원칙입니다.

4. 카테고리 종류 파악 (중복 제거)

SELECT DISTINCT category_id 
FROM products;
  • 동작 원리: products 테이블에는 수만 개의 상품이 있고, 각 상품은 카테고리 ID를 가집니다. DISTINCT 키워드를 사용하면 DB 엔진은 category_id 열의 데이터를 쭉 읽어들이면서 내부적으로 해시(Hash) 테이블을 만들거나 정렬을 수행하여 중복된 값을 하나로 병합합니다. 그 결과 고유한 ID 종류만 남게 됩니다.

Part 2. 마케팅팀의 타겟 고객 필터링

5. 특정 등급 고객

SELECT name, email 
FROM customers 
WHERE grade = 'VIP';
  • 동작 원리: WHERE 절은 조건에 맞는 **행(Row)만 필터링(Selection)**하는 역할을 합니다. 오라클에서 문자열은 반드시 홑따옴표(')로 감싸야 하며, 대소문자를 엄격하게 구분합니다('VIP'와 'vip'는 다름).

6. 날짜 기반 신규 고객

SELECT * 
FROM customers 
WHERE join_date >= TO_DATE('2023-01-01', 'YYYY-MM-DD');
  • 동작 원리: 날짜 데이터를 비교할 때는 단순 문자열('2023-01-01')로 비교하기보다는, TO_DATE() 함수를 사용하여 명시적으로 오라클의 DATE 타입으로 변환한 후 비교하는 것이 좋습니다. DB 내부에서는 날짜를 고유한 숫자 형태로 저장하므로, 부등호(>=)를 통해 쉽게 '이후' 날짜를 걸러낼 수 있습니다.

7. 특정 가격대 상품 기획전 (BETWEEN)

SELECT product_id, price 
FROM product_prices 
WHERE price BETWEEN 10000 AND 50000;
  • 동작 원리: BETWEEN A AND B는 값이 A 이상이고 B 이하(A <= value <= B)인 데이터를 찾습니다. 경계값(10000과 50000)이 **포함(Inclusive)**된다는 점이 중요합니다. 내부적으로는 price >= 10000 AND price <= 50000 으로 변환되어 실행됩니다.

8. 할인 상품 제외

SELECT product_id, price 
FROM product_prices 
WHERE price > 100000;

9. 특정 키워드 검색 1 (시작하는 문자열)

SELECT * 
FROM customers 
WHERE name LIKE '김%';
  • 동작 원리: LIKE 연산자는 패턴 매칭을 수행합니다. %(퍼센트 기호)는 '길이에 상관없이 어떤 문자라도 올 수 있음'을 의미하는 와일드카드입니다. 따라서 '김%'는 '김'으로 시작하는 모든 문자를 찾아냅니다. (단, 와일드카드가 앞에 오는 '%김' 패턴은 인덱스를 타지 못해 풀 테이블 스캔을 유발하므로 실무에서 주의해야 합니다.)

10. 특정 키워드 검색 2 (끝나는 문자열)

SELECT * 
FROM customers 
WHERE email LIKE '%@gmail.com';

11. 다중 조건 필터링 (IN)

SELECT name, department 
FROM staff 
WHERE department IN ('Sales', 'Marketing');
  • 동작 원리: IN (A, B, C)는 특정 컬럼의 값이 괄호 안의 값 중 하나라도 일치하면 조건을 만족하는 것으로 판단합니다. 내부적으로는 department = 'Sales' OR department = 'Marketing'과 동일하게 동작하지만, 조건이 많을수록 가독성이 훨씬 뛰어나며 옵티마이저가 처리하기에도 효율적입니다.

12. 복합 조건 필터링 (AND)

SELECT * 
FROM products 
WHERE category_id = 2 
  AND supplier_id = 3;
  • 동작 원리: AND 연산자는 양쪽의 조건이 **모두 참(TRUE)**일 때만 해당 행을 결과로 반환합니다.

Part 3. CS팀 및 운영팀의 데이터 점검

13. 데이터 누락 확인 1 (IS NULL)

SELECT * 
FROM customers 
WHERE grade IS NULL;
  • 동작 원리: 데이터베이스에서 NULL은 '값이 0'이거나 '빈 칸(공백)'이라는 뜻이 아니라, **'값이 아예 존재하지 않음(Unknown)'**을 의미하는 특수한 상태입니다. 따라서 = NULL 이라고 비교하면 영원히 결과를 찾을 수 없습니다. 반드시 IS NULL 연산자를 사용하여 상태를 점검해야 합니다.

14. 데이터 누락 확인 2

SELECT name 
FROM suppliers 
WHERE phone IS NULL;

15. 데이터 누락 제외 (IS NOT NULL)

SELECT * 
FROM suppliers 
WHERE phone IS NOT NULL;
  • 동작 원리: IS NOT NULL은 반대로 비어있지 않은, 즉 어떤 값이라도 정상적으로 들어가 있는 행만 추출합니다.

16. 부정 조건 검색 (!=, <>)

SELECT * 
FROM products 
WHERE supplier_id != 1;
-- 또는 WHERE supplier_id <> 1;
  • 동작 원리: 오라클에서는 같지 않음을 표현할 때 != 또는 <> 기호를 사용합니다. 둘 다 동일하게 동작하며, 지정한 값을 제외한 나머지 모든 데이터를 반환합니다.

Part 4. 영업팀의 데이터 정렬 및 리포팅

17. 기본 오름차순 정렬

SELECT * 
FROM products 
ORDER BY name ASC;
  • 동작 원리: ORDER BY는 필터링이 모두 끝난 최종 결과를 화면에 출력하기 직전에 재배열하는 역할을 합니다. ASC(Ascending)는 오름차순(가나다, ABC, 123 순서)을 의미하며, 생략 시 기본값으로 적용됩니다. 정렬은 데이터베이스에 큰 부하를 주는 작업(Sorting)이므로 꼭 필요한 경우에만 사용합니다.

18. 기본 내림차순 정렬

SELECT * 
FROM customers 
ORDER BY join_date DESC;
  • 동작 원리: DESC(Descending)는 내림차순을 의미합니다. 날짜의 경우 가장 최근 날짜(큰 값)부터 과거 날짜(작은 값) 순서로 나열됩니다.

19. 다중 정렬

SELECT * 
FROM customers 
ORDER BY join_date DESC, name ASC;
  • 동작 원리: 콤마(,)를 사용하여 정렬 기준을 여러 개 줄 수 있습니다. 먼저 join_date를 기준으로 내림차순 정렬을 수행한 후, 가입일이 완전히 동일한 데이터 그룹 내에서만 두 번째 기준인 name 오름차순 정렬이 적용됩니다.

20. 조건부 정렬 결합

SELECT * 
FROM reviews 
WHERE rating >= 4 
ORDER BY created_at DESC;
  • 동작 원리 (실행 순서): SQL은 작성된 순서와 실행되는 순서가 다릅니다. 이 쿼리는 1. FROM reviews (테이블 접근) 2. WHERE rating >= 4 (데이터 필터링) 3. SELECT * (데이터 추출) 4. ORDER BY created_at DESC (추출된 데이터를 정렬)의 순서로 내부적으로 실행됩니다. 즉, 필터링이 완전히 끝난 적은 양의 데이터를 바탕으로 마지막에 정렬을 수행하게 됩니다.