[프로그래머스]Oracle SQL_4(Lv4)

2025. 10. 2. 00:58·코딩 테스트/02. SQL

1. 년,월, 성별 별 상품 구매 회원 수 구하기

https://school.programmers.co.kr/learn/courses/30/lessons/131532?language=oracle

SELECT
    EXTRACT(YEAR FROM S.SALES_DATE) AS YEAR,
    EXTRACT(MONTH FROM S.SALES_DATE) AS MONTH,
    I.GENDER,
    COUNT(DISTINCT (S.USER_ID)) AS USERS
FROM ONLINE_SALE S
    JOIN USER_INFO I ON S.USER_ID = I.USER_ID
WHERE I.GENDER IS NOT NULL
GROUP BY EXTRACT(YEAR FROM S.SALES_DATE), EXTRACT(MONTH FROM S.SALES_DATE), I.GENDER
ORDER BY YEAR, MONTH, I.GENDER

POINT! 

1. 오라클에서 GROUP BY특징

 

  • SELECT 절의 비집계 컬럼(일반 컬)·표현식 → GROUP BY에 반드시 포함
  • 집계 함수 결과 → GROUP BY에 넣지 않음
    • 그래서 SELECT절에 회원수도 'COUNT(DISTINCT s.user_id)' GROUP BY에 미포함 
  • 별칭은 GROUP BY에서 못 씀 → 표현식을 그대로 써야 함

2. DISTINCT의 중요성

문제에서는  구매한 회원수를 집계 하라고 했습니다. 여기서 포인트는 회원수인데요

회원수는 사람을 세는 겁니다. 그래서 DISTINCT를 적용해야하죠

만약 적용하지 않았다면 한 사람이 여러번 구매한 것도 포함이 되기 때문에 그것은 구매 건수로 집계되는 겁니다.

그래서 그 달의 구매한 회원수를 구하기 위해서는 DISTINCT를 적용해야하는 거죠


2. 우유와 요거트가 담긴 장바구니

https://school.programmers.co.kr/learn/courses/30/lessons/62284?language=oracle

SELECT CART_ID
FROM (
    SELECT 
        CART_ID,
        LISTAGG(NAME, ',') WITHIN GROUP(ORDER BY NAME) AS NAME
      FROM CART_PRODUCTS 
      GROUP BY CART_ID
)
WHERE NAME LIKE '%Milk%'
    AND NAME LIKE '%Yogurt%'
ORDER BY CART_ID;

다 풀이 : LIKE 대신 HAVING을 쓰면 더 깔끔하다

SELECT CART_ID
FROM CART_PRODUCTS
GROUP BY CART_ID
HAVING SUM(CASE WHEN NAME = 'Milk' THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN NAME = 'Yogurt' THEN 1 ELSE 0 END) > 0
ORDER BY CART_ID;
  • CART_ID별로 Milk와 Yogurt가 동시에 들어간 경우만 바로 걸러낼 수 있습니다.
    문자열로 합칠 필요도 없고, LIKE의 애매한 부분(Milkshake 같은 오탐)도 방지돼요.
  • SUM은 “이름이 Milk인 행이 몇 개나 있지?”를 세기 위함입니다
👉 핵심은 "존재 여부"만 확인하면 된다는 점입니다!

1. SUM(CASE WHEN NAME='Milk' THEN 1 ELSE 0 END)
→ Milk가 있으면 1, 여러 개여도 합치면 2, 3…
→ 어쨌든 0보다 크면 Milk가 있다는 의미

2. COUNT(CASE WHEN NAME='Milk' THEN 1 END)
→ Milk인 행만 카운트
→ 역시 0보다 크면 Milk 있음

 

🔹 LISTAGG란?

  • 오라클에서 제공하는 집계 함수.
  • 여러 행(Row)의 문자열 값을 하나로 합쳐서 하나의 문자열로 반환합니다.
  • 보통 구분자(Separator)를 넣어서 표현합니다.

기본 문법

LISTAGG(컬럼명, '구분자') WITHIN GROUP (ORDER BY 정렬기준)

출력 결과

 

DEPT_ID EMP_LIST
10 Alice, Bob, Charlie
20 David, Eve

즉, 같은 부서 직원 이름을 , 로 묶어서 한 행에 보여줍니다.

구분 MySQL Oracle
문자열 합치기
(컬럼끼리 붙이기)
CONCAT(first_name, ' ', last_name) first_name || ' ' || last_name
행(Row) 값 합치기
(여러 행 → 하나의 문자열)
GROUP_CONCAT(emp_name ORDER BY emp_name SEPARATOR ', ') LISTAGG(emp_name, ', ') WITHIN GROUP (ORDER BY emp_name)

 

 

 

'코딩 테스트 > 02. SQL' 카테고리의 다른 글

[프로그래머스]Oracle SQL_6(Lv4)/UNION ALL과 CONNECT BY  (0) 2025.10.03
[프로그래머스]Oracle SQL_5(Lv4)  (0) 2025.10.02
[프로그래머스]Oracle SQL_3(Lv4)  (0) 2025.09.29
[프로그래머스]Oracle SQL_2(Lv4)  (1) 2025.09.28
[프로그래머스]Oracle SQL_1(Lv4)  (0) 2025.09.25
'코딩 테스트/02. SQL' 카테고리의 다른 글
  • [프로그래머스]Oracle SQL_6(Lv4)/UNION ALL과 CONNECT BY
  • [프로그래머스]Oracle SQL_5(Lv4)
  • [프로그래머스]Oracle SQL_3(Lv4)
  • [프로그래머스]Oracle SQL_2(Lv4)
Growth DA Log
Growth DA Log
Growth DA Log 님의 블로그 입니다.
  • Growth DA Log
    Growth DA Log님의 블로그
    Growth DA Log
  • 전체
    오늘
    어제
    • 분류 전체보기 (125)
      • TIS_COMPANY (6)
      • 코딩 테스트 (61)
        • 01. Python (3)
        • 02. SQL (58)
      • 데이터 분석 (53)
        • 01. BigQuery (9)
        • 02. GA4 (1)
        • 02-1. GA4를 더 잘 다루기 위한 마케팅 개.. (5)
        • 03. streamlit (5)
        • 04. Git (12)
        • 05. 데이터 엔지니어링 (3)
        • 06. 데이터 모델링 (11)
        • 07. Excel (0)
        • 08. Tableau (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    cross_join
    SQL
    AARRR
    revert
    tableaubootcamp
    이행성
    rank
    git
    윈도우함수
    코딩테스트
    tableau
    코테
    ROW_NUMBER
    코드잇스프린트후기
    solvesql
    Reset
    쿼리테스트
    streamlit
    DENSE_RANK
    프로그래머스
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
Growth DA Log
[프로그래머스]Oracle SQL_4(Lv4)
상단으로

티스토리툴바