한 줄 요약전화번호 앞 세 자리를 '010'으로 고정하면 다른 번호가 틀어진다. 번호는 TLNO에서 SUBSTR로 잘라 붙이고, 주소는 CONCAT_WS로 이어 붙인다.
쉽게 말하면전화번호부를 옮겨 적으면서 앞자리를 전부 "010"으로 써 버리면, 011을 쓰던 사람 번호가 틀린다. 원래 적힌 그대로 잘라 옮겨야 한다.
FAIL · 원문 기록2026.10.02 · 21회차
문제 원문 · 제출 코드 · 정답 풀이
제출 코드 · 오답노트 원문
SELECT DISTINCT U.USER_ID, U.NICKNAME,
CONCAT(U.CITY, ' ', U.STREET_ADDRESS1, ' ', U.STREET_ADDRESS2) AS 전체주소,
CONCAT('010','-',SUBSTR(U.TLNO,4,4),'-',SUBSTR(U.TLNO,8,4)) AS 전화번호
FROM USED_GOODS_BOARD G JOIN USED_GOODS_USER U ON G.WRITER_ID = U.USER_ID
WHERE G.WRITER_ID IN (SELECT WRITER_ID from USED_GOODS_BOARD
group by WRITER_ID having count(*) >= 3)
ORDER BY U.USER_ID DESC;
정답 풀이 · 오답노트 원문
SELECT U.USER_ID, U.NICKNAME,
CONCAT_WS(' ', U.CITY, U.STREET_ADDRESS1, U.STREET_ADDRESS2) AS 전체주소,
CONCAT(SUBSTR(U.TLNO, 1, 3), '-', SUBSTR(U.TLNO, 4, 4), '-', SUBSTR(U.TLNO, 8, 4)) AS 전화번호
FROM USED_GOODS_USER U
JOIN USED_GOODS_BOARD B ON U.USER_ID = B.WRITER_ID
GROUP BY U.USER_ID
HAVING COUNT(*) >= 3
ORDER BY U.USER_ID DESC;
"글 3개 이상 쓴 사람" 고르기는 제출 코드(WHERE IN 서브쿼리 + DISTINCT)와 정답 풀이(GROUP BY + HAVING)가 같은 결과를 낸다. 차이는 출력 형식이다.
- 전화번호 — 제출 코드는 앞 세 자리를
'010'으로 고정했다. TLNO가 011로 시작하면 010-…으로 잘못 찍힌다. 실제 채점 데이터를 볼 수 없어 이것이 FAIL의 원인이라고 단정할 수는 없지만, 가장 분명한 차이다. - 주소 — MySQL의
CONCAT은 인자 하나라도 NULL이면 결과 전체가 NULL이다. CONCAT_WS(구분자, …)는 사이사이에 구분자를 넣고 NULL은 건너뛴다. SUBSTR(문자열, 시작, 길이) — SQL은 1부터 센다(자바 substring은 0부터).- WHERE vs HAVING — WHERE는 묶기 전의 행을, HAVING은
GROUP BY로 묶은 뒤의 그룹을 거른다. 집계 함수 조건은 HAVING에. - 정답 풀이는
GROUP BY U.USER_ID만 쓰고 닉네임·주소를 SELECT한다. USER_ID가 기본 키라 MySQL 5.7 이상은 나머지 컬럼이 USER_ID로 정해진다고 보고 허용한다. 기본 키가 아닌 컬럼으로 묶을 때는 SELECT의 컬럼을 GROUP BY에도 적는다.
로컬 검증 — SQLite, MySQL의 CONCAT 규칙으로 등록
제출 코드: user011|엘사|…|010-9876-5432 (실제 번호 011-9876-5432)
noaddr2|널|NULL|010-1111-2222 (상세 주소 NULL → 주소 전체 NULL)
정답 풀이: user011|엘사|…|011-9876-5432
noaddr2|널|서울시 종로구 종로 1|010-1111-2222
고르는 사람 4명은 두 방식이 같음 · 글 2개인 사람은 둘 다 제외SQL 파일을 그대로 읽어 Node 내장 SQLite(메모리 DB)에서 실행했다. SQLite의 CONCAT은 NULL을 빈 문자열로 치므로 MySQL처럼 NULL을 돌려주는 같은 이름의 함수를 등록했다. 011 번호·NULL 상세 주소는 차이를 보이려고 넣은 데이터다.