2026. 3. 4. 16:58ㆍ프로그래머스:sql 고득점 Kit
문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/276035
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
유튜브: https://youtu.be/1v70HzFfw98
틀린 정답
WITH X AS (
SELECT ID FROM SKILLCODES AS C JOIN DEVELOPERS AS D ON
D.SKILL_CODE & C.CODE > 1
WHERE CATEGORY = 'Front End'
)
SELECT ID,EMAIL,FIRST_NAME,LAST_NAME FROM DEVELOPERS AS D INNER JOIN X USING(ID) ORDER BY ID
피드백
1. 비트 연산 조건식 (D.SKILL_CODE & C.CODE > 1)
SKILLCODES의 CODE는 2의 제곱수(1, 2, 4, 8, 16...)로 이루어져 있습니다.
만약 어떤 'Front End' 스킬의 CODE 값이 가장 작은 2의 제곱수인 1이라고 가정해 보겠습니다.
어떤 개발자가 이 스킬을 가지고 있다면 D.SKILL_CODE & 1의 연산 결과값은 무엇이 될까요?
그리고 그 결과값이 작성하신 조건식인 > 1을 참(True)으로 통과할 수 있을까요?
2. 만약 어떤 개발자가 'Front End' 카테고리에 속하는 스킬을 2개 이상 (예: React와 Vue 모두) 가지고 있다고 가정해 보겠습니다.
작성하신 WITH X 절의 쿼리를 실행했을 때, 이 다재다능한 개발자의 ID는 임시 테이블 X에 몇 줄(row)이 생성될까요?
그리고 그 결과가 마지막 SELECT 문을 거치면 최종 결과물에 어떤 영향을 미치게 될까요?
Q&A
질문
GROUP BY ID 를 해서 ID로 묶어버리는 것과 마지막 출력할 때 DISTINCT를 하는 것 중 뭐가 더 효율적이야?
답변
결론부터 말씀드리면, 지금 상황에서는 DISTINCT를 사용하는 것이 더 적절하고 효율적인 선택입니다. 그 이유는 두 키워드의 원래 목적을 비교해 보면 알 수 있습니다.
DISTINCT: 결과 집합에서 단순히 중복된 행(Row)을 제거하는 데 특화되어 있습니다. "이 데이터들 중에서 중복 없는 고유한 값만 보여줘"라는 의도를 데이터베이스에 가장 직관적으로 전달합니다.
GROUP BY: 데이터를 특정 컬럼 기준으로 묶은 뒤, 그 묶음 안에서 합계(SUM), 평균(AVG), 개수(COUNT) 같은 집계 연산을 수행하는 것이 주 목적입니다.
집계 없이 중복 제거용으로만 쓴다면, 문법 규칙에 따라 SELECT에 있는 모든 컬럼(ID, EMAIL, FIRST_NAME, LAST_NAME)을 GROUP BY 뒤에 전부 적어주어야 해서 코드가 불필요하게 길어질 수 있습니다.
최신 데이터베이스들은 내부적으로 이 두 방식을 비슷하게 최적화하여 실행하기 때문에 실제 연산 속도 차이는 미미한 편입니다. 하지만 코드의 가독성과 명확한 의도 전달을 고려했을 때는 DISTINCT가 이 문제에 딱 맞는 도구입니다.
나의 정답
WITH X AS (
SELECT ID FROM SKILLCODES AS C JOIN DEVELOPERS AS D ON
D.SKILL_CODE & C.CODE > 0
WHERE CATEGORY = 'Front End'
)
SELECT DISTINCT ID,EMAIL,FIRST_NAME,LAST_NAME FROM DEVELOPERS AS D INNER JOIN X USING(ID) ORDER BY ID
다른 사람의 정답
SELECT
ID,
EMAIL,
FIRST_NAME,
LAST_NAME
FROM DEVELOPERS
WHERE (SKILL_CODE & (SELECT SUM(CODE) FROM SKILLCODES WHERE CATEGORY LIKE 'Front%'))
ORDER BY ID
피드백
이전 코드 (JOIN + DISTINCT): DEVELOPERS 테이블과 SKILLCODES 테이블을 결합하면서 개발자가 가진 스킬 개수만큼 중복된 데이터를 메모리에 임시로 만들어냅니다.
그 후 무거워진 데이터 속에서 DISTINCT를 사용해 중복을 다시 하나하나 찾아 지워야 하므로 작업량과 메모리 사용량이 많습니다.
현재 코드 (서브쿼리 마스킹): 괄호 안의 서브쿼리 SELECT SUM(CODE)...가 가장 먼저 실행되어 'Front End 스킬들의 총합(하나의 숫자 마스크)'을 딱 한 번만 계산해 냅니다.
그 후 DEVELOPERS 테이블을 처음부터 끝까지 딱 한 번씩만 훑으면서 비트 연산(&)만 수행하면 끝납니다. 불필요한 중복 데이터가 아예 생성되지 않는 아주 깔끔한 방식이죠!
Q&A
질문WHERE (SKILL_CODE & (SELECT SUM(CODE) FROM SKILLCODES WHERE CATEGORY LIKE 'Front%')) >0
이렇게 안하고 그냥
WHERE (SKILL_CODE & (SELECT SUM(CODE) FROM SKILLCODES WHERE CATEGORY LIKE 'Front%'))
이렇게 해도 되는거야?
답변
결론부터 말씀드리면, 프로그래머스 같은 코딩 테스트에서 주로 사용하는 MySQL 환경에서는 그렇게 작성하셔도 완전히 똑같이 정답으로 작동합니다!
그 이유를 이해하려면 데이터베이스가 WHERE 절을 어떻게 읽어들이는지 알아야 해요.
WHERE 절은 조건식의 결과가 참(True)인지 거짓(False)인지만 판단해서 데이터를 걸러냅니다.
그런데 컴퓨터(특히 MySQL)의 세계에서는 숫자를 참과 거짓으로 판단할 때 아주 재미있는 규칙이 하나 있습니다.
연산 결과값이 0이라면 거짓(False)으로 대우하고, 0이 아닌 모든 숫자(예: 16, 256 등)는 전부 참(True)으로 대우한다는 규칙이죠!
'프로그래머스:sql 고득점 Kit' 카테고리의 다른 글
| 상품을 구매한 회원 비율 구하기 (0) | 2026.03.08 |
|---|---|
| 5월 식품들의 총매출 조회하기 (0) | 2026.03.03 |
| 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기 (0) | 2026.03.02 |
| 주문량이 많은 아이스크림들 조회하기 (0) | 2026.03.01 |
| 그룹별 조건에 맞는 식당 목록 출력하기 (0) | 2026.02.26 |