[프로그래머스]Lv3. 헤비 유저가 소유한 장소; 중첩 서브쿼리
https://school.programmers.co.kr/learn/courses/30/lessons/77487
1. Problem
공간 대여 플랫폼에서 공간을 2개 이상 등록한 '헤비 유저'를 식별하고, **그들이 등록한 모든 공간의 정보(ID, 이름, 호스트 ID)**를 출력해야 한다. 단순히 헤비 유저의 명단만 뽑는 것이 아니라, 그들에게 속한 '전체 리스트'를 다시 보여줘야 한다는 점이 이 문제의 핵심이다.
2. Solution: 서브쿼리를 이용한 필터링
먼저 서브쿼리를 통해 헤비 유저의 HOST_ID 목록을 만들고, 메인 쿼리에서 이를 IN 연산자로 필터링하여 해당 호스트의 모든 행을 가져온다.
3. Takeaway: 왜 메인 쿼리에 바로 GROUP BY를 쓰면 안 될까?
- 집계 함수의 제약 (The Grouping Trap): 유진 님의 오답처럼 메인 쿼리에 GROUP BY HOST_ID를 쓰면, SQL 엔진은 호스트당 결과를 단 한 줄로 압축하려고 시도한다. 하지만 한 호스트가 여러 개의 ID와 NAME을 가졌을 경우, 엔진은 어떤 값을 보여줘야 할지 결정할 수 없어 에러를 발생시키거나 데이터 유실을 초래한다.
- 전체 데이터를 유지하며 필터링하기: 특정 집단의 '상세 내역'을 모두 보고 싶을 때는 [필터링 기준 추출(서브쿼리) -> 대상 매칭(메인 쿼리)] 구조가 객관적으로 가장 안전하고 효율적이다.
- 가독성과 정합성: 서브쿼리를 사용하면 "누가 헤비 유저인가?"라는 비즈니스 로직과 "그들의 정보를 보여준다"는 출력 로직이 분리되어 쿼리의 가독성이 높아진다.
PLACES is a table containing information of spaces for rent that are registered on a space rental platform. The structure of PLACES is as follows, where each of ID, NAME, and HOST_ID represents space ID, name of space, and landlord ID. ID is the primary key.
| NAME | TYPE |
| ID | INT |
| NAME | VARCHAR |
| HOST_ID | INT |
Problem
In this platform, landlords who have registered two or more spaces are called "heavy users". Please write an SQL statement that returns the information of spaces registered by heavy users. Sort them by ID.
Example
Suppose PLACES is as follows:
| ID | NAME | HOST_ID |
| 4431977 | BOUTIQUE STAYS - Somerset Terrace, Pet Friendly | 760849 |
| 5194998 | BOUTIQUE STAYS - Elwood Beaches 3, Pet Friendly | 760849 |
| 16045624 | Urban Jungle in the Heart of Melbourne | 30900122 |
| 17810814 | Stylish Bayside Retreat with a Luscious Garden | 760849 |
| 22740286 | FREE PARKING - The Velvet Lux in Melbourne CBD | 30900122 |
| 22868779 | ★ Fresh Fitzroy Pad with City Views! ★ | 21058208 |
- Landlord 760849 registered three spaces, which makes her a heavy user.
- Landlord 30900122 registered two spaces, which makes her a heavy user.
- Landlord 21058208 registered one space, which makes her not a heavy user.
Therefore, your SQL statement must return the following:
| ID | NAME | HOST_ID |
| 4431977 | BOUTIQUE STAYS - Somerset Terrace, Pet Friendly | 760849 |
| 5194998 | BOUTIQUE STAYS - Elwood Beaches 3, Pet Friendly | 760849 |
| 16045624 | Urban Jungle in the Heart of Melbourne | 30900122 |
| 17810814 | Stylish Bayside Retreat with a Luscious Garden | 760849 |
| 22740286 | FREE PARKING - The Velvet Lux in Melbourne CBD | 30900122 |
1. 정답 쿼리
SELECT ID, NAME, HOST_ID
FROM PLACES
WHERE HOST_ID IN (SELECT HOST_ID FROM PLACES
GROUP BY HOST_ID
HAVING COUNT(*) >=2)
ORDER BY ID;
서브쿼리 부분 (SELECT HOST_ID FROM PLACES ...):
- GROUP BY HOST_ID: 호스트별로 데이터를 묶습니다.
- HAVING COUNT(ID) >= 2: 그중 등록된 공간이 2개 이상인 호스트의 ID만 필터링합니다. (이들이 바로 '헤비 유저'입니다.)
2. 나의 오답
SELECT ID, NAME, HOST_ID
FROM PLACES
GROUP BY HOST_ID
HAVING COUNT(*) >= 2
ORDER BY ID;
문제점
- 집계 함수의 제약: GROUP BY HOST_ID를 사용하면 SQL은 데이터를 '호스트 ID'라는 덩어리로 묶어버린다. 이때 SELECT 절에는 그룹화의 기준인 HOST_ID나 COUNT(*), SUM() 같은 집계 함수만 올 수 있다. ID나 NAME은 한 호스트 안에 여러 개가 존재할 수 있기 때문에, 컴퓨터는 "이 호스트의 여러 이름 중 어떤 걸 보여줘야 하지?"라고 판단하지 못해 에러를 낸다.
- 데이터의 누락: 목적은 '헤비 유저가 가진 모든 공간의 정보'를 보는 것이지만, 위 쿼리가 작동한다 하더라도 호스트당 단 하나의 행만 보여주게 된다.
'Data Science > SQL' 카테고리의 다른 글
| [SQL/오답] 날짜 그룹화와 특수문자 별칭 (프로그래머스 Lv2) (0) | 2026.02.14 |
|---|---|
| [SQL/오답] '동시 구매' 조건: COUNT(*)와 COUNT(DISTINCT) 차이 (프로그래머스 Lv4) (0) | 2026.02.14 |
| [SQL/오답] 문자열 결합(CONCAT)과 서브쿼리를 이용한 조건부 경로 추출 (프로그래머스 Lv3) (0) | 2026.02.12 |
| [SQL/오답] WITH RECURSIVE: 존재하지 않는 시간대 0으로 채우기 (프로그래머스 Lv4) (1) | 2026.02.12 |
| [SQL/오답] 정규표현식(REGEXP)의 대소문자 함정과 이메일 유효성 검사 (LeetCode1517 Easy) (0) | 2026.02.10 |