안녕하세요! 데코입니다!
오늘은 프로그래머스 코딩테스트 연습에 있는 "특정 형질을 가지는 대장균 찾기" 문제를 포스팅하려고 합니다!
바로 포스팅 시작할게요! :)
(출처 : https://school.programmers.co.kr/learn/courses/30/lessons/301646)
1. 문제 : 특정 형질을 가지는 대장균 찾기(Lv. 1)
2. 문제 설명
대장균들은 일정 주기로 분화하며,
분화를 시작한 개체를 부모 개체, 분화가 되어 나온 개체를 자식 개체라고 합니다.
다음은 실험실에서 배양한 대장균들의 정보를 담은 ECOLI_DATA 테이블입니다.
ECOLI_DATA 테이블의 구조는 다음과 같으며,
ID, PARENT_ID, SIZE_OF_COLONY, DIFFERENTIATION_DATE, GENOTYPE 은 각각
대장균 개체의 ID, 부모 개체의 ID, 개체의 크기, 분화되어 나온 날짜, 개체의 형질을 나타냅니다.
[ 테이블 구조('FISH_INFO') ]
COLUMN NAME | TYPE | NULLABLE |
ID | INTEGER | FALSE |
PARENT_ID | INTEGER | TRUE |
SIZE_OF_COLONY | INTEGER | FALSE |
DIFFERENTIATION_DATE | DATE | FALSE |
GENOTYPE | INTEGER | FALSE |
최초의 대장균 개체의 PARENT_ID는 NULL 값입니다.
[ 문제 ]
2번 형질이 보유하지 않으면서 1번이나 3번 형질을 보유하고 있는 대장균 개체의 수(COUNT)를 출력하는 SQL 문을 작성해 주세요.
1번과 3번 형질을 모두 보유하고 있는 경우도
1번이나 3번 형질을 보유하고 있는 경우에 포함합니다.
[ 예시 ]
예를 들어 ECOLI_DATA 테이블이 다음과 같다면
ID | PARENT_ID | SIZE_OF_COLONY | DIFFERENTIATION_DATE | GENOTYPE |
1 | NULL | 10 | 2019/01/01 | 8 |
2 | NULL | 2 | 2019/01/01 | 15 |
3 | 2 | 100 | 2020/01/01 | 1 |
4 | 2 | 16 | 2020/01/01 | 13 |
각 대장균 별 형질을 2진수로 나타내면 다음과 같습니다.
ID 1 : 1000₍₂₎
ID 2 : 1111₍₂₎
ID 3 : 1₍₂₎
ID 4 : 1101₍₂₎
각 대장균 별 보유한 형질을 다음과 같습니다.
ID 1 : 4
ID 2 : 1, 2, 3, 4
ID 3 : 1
ID 4 : 1, 3, 4
따라서 2번 형질이 없는 대장균 개체는 ID 1, ID 3, ID 4 이며
이 중 1번이나 3번 형질을 보유한 대장균 개체는 ID 3, ID 4입니다.
따라서 결과는 다음과 같아야 합니다.
[ 출력 결과 ]
COUNT |
2 |
3. 문제 풀이
-- 1안
SELECT COUNT(*) AS COUNT
FROM ECOLI_DATA A
WHERE 1=1
AND (GENOTYPE & 2) != 2
AND ((GENOTYPE & 4) = 4 OR (GENOTYPE & 1) = 1)
이번 문제는 총 1안 한 가지로 작성했습니다!
# 1안 풀이 설명
# [ 문제 접근 설명 ]
문제를 읽고 조건에 맞는 쿼리를 작성하기 위해서 다음과 같이 두 가지 단계로 진행했어요!
1. ECOLI_DATA 테이블에서 조건에 맞는 데이터 추출하기(WHERE)
2. 추출한 데이터의 개수 세기(COUNT 함수)
# [ 1안 쿼리 작성 설명 ]
1 첫 번째 단계에서가 이 문제의 전부라고 생각이 드네요!
이진법이 나와서 조금 생소했는데, 문제를 읽어보면 이진법으로 변환한 후에
2번 형질은 보유하지 않아야 합니다.
또한 1번 혹은 3번의 형질은 보유해야 하기 때문에
이를 비트 연산을 이용해서, 작성하면 아래와 같습니다.
SELECT *
FROM ECOLI_DATA A
WHERE 1=1
AND (GENOTYPE & 2) != 2
AND ((GENOTYPE & 4) = 4 OR (GENOTYPE & 1) = 1)
비트 연상에 대해서 간단하게 설명하면, 비트연산은 각 비트 단위로 연산을 수행하는 것인데요!
두 숫자의 각 비트를 비교하여 둘 다 1인 경우에만 1을 반환합니다.
예를 들어서 보여드리면 GENOTYPE = 5 (2진수로 101)
GENOTYPE & 2
= 101 & 010
= 거짓 거짓 거짓
= 0
따라서, 결과는 000으로 0이 됩니다.
이렇게 비트 연산을 통해 조건문에 넣어서 2번의 형질을 가지는 것은 포함이 되지 않고
1번 혹은 3번의 형질을 가지는 데이터만을 추출하였습니다!
2 두 번째 단계에서는 COUNT() 함수를 이용해서 필터링한 데이터의 숫자를 산출했습니다!
이후 문제에서 요청한 것과 같이 값을 COUNT로 칭해주었습니다.
SELECT COUNT(*) AS COUNT
FROM ECOLI_DATA A
WHERE 1=1
AND (GENOTYPE & 2) != 2
AND ((GENOTYPE & 4) = 4 OR (GENOTYPE & 1) = 1)
4. 데코의 문제 풀이 후기
이번 문제에는 LEVEL 1 이지만 비트연산을 물어보는 문제였습니다.
이진법이 나오면 당황스러운데, 문제를 읽으면서 요구하는 사항을 파악하고
쿼리를 차근차근 작성하면 결국에는 다 작성이 되는 것 같습니다.
"&"를 통해 비트연산을 수행하는 것도 자주 사용하는 것은 아니지만, 참고하면 좋을 것 같아요!
혹시나 더 좋은 쿼리나 어렵게 느껴지신 부분이 있다면 댓글로 남겨주세요!
오늘 문제에서 설명이 어려운 부분 혹은 잘 이해가 안 가는 부분
그리고 더 궁금한 내용이 있다면
언제든지 댓글로 남겨주세요!
빠르게 궁금증을 해결해 드릴게요!
공감과 댓글은 큰 힘이 됩니다!
오늘도 블로그 방문해 주시고
포스팅 읽어주셔서 감사합니다!
'Skill Sets > SQL' 카테고리의 다른 글
[SQL] 연도별 대장균 크기의 편차 구하기(프로그래머스/MySQL/Level 2) (46) | 2024.07.07 |
---|---|
[SQL / 질문과 답변] WHERE 1=1 사용하는 이유 (41) | 2024.06.30 |
[SQL] 잡은 물고기 중 가장 큰 물고기의 길이 구하기(프로그래머스/MySQL/Level 1) (38) | 2024.06.29 |
[SQL] 특정 물고기 잡은 수 구하기(프로그래머스/MySQL/Level 2) (36) | 2024.06.28 |
[SQL] 한 해에 잡은 물고기 수 구하기(프로그래머스/MySQL/Level 1) (35) | 2024.06.22 |