SQL

[프로그래머스/MySQL] 특정 형질을 가지는 대장균 찾기 / 비트 연산

AKIRA24 2024. 7. 17. 19:39
728x90

문제 설명

대장균들은 일정 주기로 분화하며, 분화를 시작한 개체를 부모 개체, 분화가 되어 나온 개체를 자식 개체라고 합니다.
다음은 실험실에서 배양한 대장균들의 정보를 담은 ECOLI_DATA 테이블입니다. ECOLI_DATA 테이블의 구조는 다음과 같으며, ID, PARENT_ID, SIZE_OF_COLONY, DIFFERENTIATION_DATE, GENOTYPE 은 각각 대장균 개체의 ID, 부모 개체의 ID, 개체의 크기, 분화되어 나온 날짜, 개체의 형질을 나타냅니다.

Column name Type Nullable
ID INTEGER FALSE
PARENT_ID INTEGER TRUE
SIZE_OF_COLONY INTEGER FALSE
DIFFERENTIATION_DATE DATE FALSE
GENOTYPE INTEGER FALSE

 

문제

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 입니다.

정답

    select count(*) as Count
    from ECOLI_DATA 
    where GENOTYPE&2 = 0 and (GENOTYPE&1 != 0 or GENOTYPE&4 != 0 )

 

풀이

비트연산 사용에 대해 모르는 부분이 있어 해설을 참고하게 되었다.

 

먼저 비트 연산자에 대해 알아보면

기호 내용
& AND 연산, 둘 다 참일경우 만족
| OR 연산, 둘 중 하나만 참이여도 만족
^ XOR연산, 둘중 하나만 참일 경우 만족
~ 보수 연산
<< 왼쪽 시프트 연산자, 변수의 값을 왼쪽으로 지정된 비트 수 만큼 이동
>> 오른쪽 시프트 연산자, 변수의 값을 오른쪽으로 지정된 비트 수 만큼 이동

 

여기서 AND연산자인 '&'를 사용한 문제였다.

그리고 조금 헷갈리던 부분인 형질 1,2,3,4에 대한 내용을 조금 더 이해하기 쉬운 방법으로 찾아보았다.

형질 1 = 0001(2) -> 1
형질 2 = 0010(2) -> 2
형질 3 = 0100(2) -> 4
형질 4 = 1000(2) -> 8

형질ID 2진법 GENOTYPE 풀이
1 1000 8 1000 -> 8
2 1111 15 1000-> 8, 0100->4, 0010->2, 0001-> 1 
8 + 4 + 2 + 1 = 15
3 1 1 0001 -> 1
4 1101 13 1000 -> 8, 0100 -> 4, 0001-> 1
8 + 4 + 1 = 13

형질 1,2,3,4 는 2진법 값에서 1의 위치를 나타내는 것 이였고,

따라서 형질 2를 포함하지 않으며 1,3을 포함한 형질을 골라내기위해

WHERE, AND, OR을 사용했다.

    where GENOTYPE&2 = 0

1)  where GENOTYPE&2 = 0

첫번째로 where 절에서 &연산을 사용 GENOTYPE과 2 두개가 참의 값인 경우가 아닌 것들이라는 조건을 작성하고

 

    and (GENOTYPE&1 != 0 or GENOTYPE&4 != 0 )

 

2) and (GENOTYPE&1 != 0 or GENOTYPE&4 != 0 )

첫번째 조건인 형질2가 아닌 것에 and 를 사용해 두번째 조건으로 1과 4가 FALSE가 아닌 경우를 사용해

형질 2를 포함하지 않으며 1이나 3을 포함한 형질ID를 찾을 수 있었다.

 

비트연산에 대해 모르는 상태로 문제를 만나게 되었고, 어떻게 풀어나가는 지를 중점으로 보고 찾아보며 공부를 하게 된 것 같다.