코딩 테스트 연습/[프로그래머스][리트코드] MySQL

[LV.4] String, Date > 조건에 맞는 사용자 정보 조회하기

duswjd_data 2025. 6. 20. 10:32

문제

https://school.programmers.co.kr/learn/courses/30/lessons/164670

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

  • USED_GOODS_BOARD와 USED_GOODS_USER 테이블에서 중고 거래 게시물을 3건 이상 등록한 사용자의 사용자 ID, 닉네임, 전체주소, 전화번호를 조회하는 SQL문을 작성
  • 이때, 전체 주소는 시, 도로명 주소, 상세 주소가 함께 출력되도록 하기
  • 전화번호의 경우 xxx-xxxx-xxxx 같은 형태로 하이픈 문자열(-)을 삽입하여 출력
  • 결과는 회원 ID를 기준으로 내림차순 정렬

문제 설명

  • 중고 거래 게시판 정보를 담은 USED_GOODS_BOARD 테이블
  • 중고 거래 게시판 첨부파일 정보를 담은 USED_GOODS_USER 테이블

정답 코드

SELECT U.USER_ID,
       U.NICKNAME,
       CONCAT(U.CITY, ' ', U.STREET_ADDRESS1, ' ', U.STREET_ADDRESS2) 전체주소,
       CONCAT(SUBSTR(U.TLNO,1,3),'-', SUBSTR(U.TLNO,4,4), '-', SUBSTR(U.TLNO,8,4)) 전화번호
FROM USED_GOODS_USER U JOIN
(SELECT WRITER_ID
 FROM USED_GOODS_BOARD
 GROUP BY WRITER_ID
 HAVING COUNT(*)>=3
)B ON U.USER_ID = B.WRITER_ID
ORDER BY U.USER_ID DESC

코드 설명

1. 서브쿼리

SELECT WRITER_ID
FROM USED_GOODS_BOARD
GROUP BY WRITER_ID
HAVING COUNT(*)>=3

 

  • USED_GOODS_BOARD에서 작성자(WRITER_ID)별로 게시글 수를 그룹화
  • 게시글이 3건 이상인 사용자만 선별

2. 메인 쿼리

  • 서브쿼리 결과와 USED_GOODS_USER 테이블을 JOIN하여 사용자 정보를 가져옴
  • 조건: U.USER_ID = WRITER_ID

3. SELECT절

  • USER_ID
  • NICKNAME
  • 전체주소
    • CITY, STREET_ADDRESS1, STREET_ADDRESS2를 공백으로 연결해 출력
    • CONCAT(U.CITY, ' ', U.STREET_ADDRESS1, ' ', U.STREET_ADDRESS2)
  • 전화번호
    • TLNO를 010-1234-5678 형태로 가공
    • CONCAT(SUBSTR(U.TLNO,1,3), '-', SUBSTR(U.TLNO,4,4), '-', SUBSTR(U.TLNO,8,4))

4. 정렬

  • ORDER BY U.USER_ID DESC
    • 사용자 ID를 기준으로 내림차순 정렬

 


첫 번째 시도 (실패. 오류)

SELECT U.USER_ID,
       U.NICKNAME,
       (U.CITY+U.STREET_ADDRESS1+U.STREET_ADDRESS2) 전체주소,
       CONCAT(U.TLNO[:2],'-', U.TLNO[3:6], '-', U.TLNO[7:], '-') 전화번호
FROM USED_GOODS_BOARD B JOIN USED_GOODS_USER U ON B.WRITER_ID = U.USER_ID
WHERE COUNT(B.WRITER_ID)>=3

오류 이유

  • (U.CITY+U.STREET_ADDRESS1+U.STREET_ADDRESS2)
    • `+ 연산자`는 숫자 덧셈 (문자열을 붙이려면 CONCAT() 사용)
  • CONCAT(U.TLNO[:2],'-', U.TLNO[3:6], '-', U.TLNO[7:], '-')
    • Python 인덱싱 (Python이랑 같이 하면서 헷갈리지 말기!!)
    • SQL에서는 SUBSTR() 또는 LEFT/RIGHT/MID 등을 사용
  • WHERE COUNT(B.WRITER_ID) >= 3
    • WHERE절에서는 COUNT() 같은 집계 함수 사용 불가 (기초적인거 까먹지 말자,,)
    • 집계는 GROUP BY와 함께 HAVING절에서 사용

 두 번째 시도 (실패)

SELECT U.USER_ID,
       U.NICKNAME,
       CONCAT(U.CITY, ' ', U.STREET_ADDRESS1, ' ', U.STREET_ADDRESS2) 전체주소,
       CONCAT(SUBSTR(U.TLNO,1,3),'-', SUBSTR(U.TLNO,4,4), '-', SUBSTR(U.TLNO,8,4)) 전화번호
FROM USED_GOODS_BOARD B JOIN USED_GOODS_USER U ON B.WRITER_ID = U.USER_ID
GROUP BY U.USER_ID, U.NICKNAME
HAVING COUNT(U.USER_ID)>=3

 


틀린 이유

  • CONCAT(...)도 GROUP BY에 포함해야 함 (집계함수가 아니므로)
    • GROUP BY절에 포함하거나
    • GROUP BY 쓰지 않고 서브쿼리 활용
  • 내림차수 정렬 잊지말고 추가하기

세 번째 시도 (성공)

SELECT U.USER_ID,
       U.NICKNAME,
       CONCAT(U.CITY, ' ', U.STREET_ADDRESS1, ' ', U.STREET_ADDRESS2) 전체주소,
       CONCAT(SUBSTR(U.TLNO,1,3),'-', SUBSTR(U.TLNO,4,4), '-', SUBSTR(U.TLNO,8,4)) 전화번호
FROM USED_GOODS_USER U JOIN
(SELECT WRITER_ID
 FROM USED_GOODS_BOARD
 GROUP BY WRITER_ID
 HAVING COUNT(*)>=3
)B ON U.USER_ID = B.WRITER_ID
ORDER BY U.USER_ID DESC
  • 참고) MySQL에서는 SUBSTR()과 SUBSTRING()이 같지만, 협업 시 SUBSTRING() 선호할 수 있음