[사전캠프] TIL 작성 - 24.08.21(수)

2024. 8. 21. 23:40내일배움캠프

1. 학습

 오늘은 마지막 남은 SQL 기초 강의를 완강하였다. 하지만 마지막이여서 그런지 장애물이 있었는데 바로 'Pivot Table' 을 배우는 과정에서 굉장한 답답함을 느꼈다. 일단 아래의 코드가 문제의 코드였다.

select age,
       max(if(gender='male', order_count, 0)) male,
       max(if(gender='female', order_count, 0)) female
from 
(
select b.gender,
       case when age between 10 and 19 then 10
            when age between 20 and 29 then 20
            when age between 30 and 39 then 30
            when age between 40 and 49 then 40
            when age between 50 and 59 then 50 end age,
       count(1) order_count
from food_orders a inner join customers b on a.customer_id=b.customer_id
where b.age between 10 and 59
group by 1, 2
) t
group by 1
order by age

 

 실습 예제를 따라하는 과정이었다. 어제는 제대로 수강을 못들어 오늘 다시 한 번 들을 강의에서 나온 내용이었는데, 도대체 본 쿼리의 'MAX' 함수를 왜 쓰는지 이유를 몰라 강의를 다시 들어봤지만 강의에선 '~이렇게 이해하시는게 편하실꺼예요~' 라는 말만 나오고 어떻게 흘러 원하는 결과가 나오는지에 대한 내용이 없었다. 너무 답답해 검색을 해보았지만 원하는 답을 찾기 어려워 직접 테스트를 이리저리 해본 결과 결국 원하는 답이 아닐까하는 결과에 도달했다.

서브쿼리 결과 테이블 일부

 

 위 이미지 처럼 'cuisine_type(음식종류)' 컬럼으로 서브쿼리 결과 테이블을 그룹화(GROUP BY) 했다면 아마 해당 컬럼 값에 따라 해당 레코드들이 그룹화 되었을 것이다. 'American 그룹', 'Chinese 그룹' 이런 식으로 말이다 그리고 각 레코드들은 'age(나이대)' 에 따른 회원의 수 정보를 각각 가지고 있을 것이다. 자 이 상태에서 본 쿼리에 있는 문제의 'MAX~' 구문을 만나면 어떻게 될까? 설명을 위해 내가 주 언어로 사용하는 Java 릍 통해 예시를 들겠다.

// 음식 종류가 'American' 인 그룹 레코드에 대한 예시

int[] american = {58, 55,54, 60, 59};	// 순차적으로 10, 20, 30, 40, 50 대 주문수
int[] result = new int[american.lengt]; // 실제 데이터가 변하지 않으므로 설명을 위해 추가

// 여기서 부터 'MAX(IF(~~))' 절을 만났을 때
int ageRange = 비교나이대;
for (int i = 0; i < result.length; i++) {
	if (a == ageRange) {
    	result[i] = american[i];
    } else {
    	result[i] = 0;
    }
}

 

자 그룹화 된 음식 종류 중 'American' 에 해당하는 레코드들의 'order_count(주문수)' 가 배열에 저장되어있다. 여기서 'MAX' 절을 만나면 조건문에 있는 'age = 10' 의 조건식의 '10' 이 위 예시 코드의 'ageRange' 에 저장되었다고 가정하자.

 

 이후 그룹의 모든 'age' 컬럼 값을 IF 절 한 줄과 for 문 마냥 전부 비교하는 것이다. 그러면 결과적으로 해당 정수와 같은 값을 갖는 경우 실제 'order_count' 이 남을 것이고 나머지 레코드들에 대해서는 '0' 이 남는 것이다. 위의 예시에 따르면, 결과가 'age = 10' 일 경우 'result = {58, 0, 0, 0, 0};' 이 되는 것이다.

 

 이제 드디어 문제의 MAX 함수가 등장한다. MAX 는 이 결과 중에 가장 큰 값을 선택한다. 그렇다 나머지가 다 '0' 을 가지니 자연스레 10대의 주문에 해당하는 '58' 을 선택(반환)하는 것이다. 그리고 이 값은 '10대' 라고 별명을 지정한 컬럼과 해당 그룹 값('American') 과 교차하는 지점에 저장(조회)되는 것이다.

 

 이렇다 보니 SUM 을 사용해도 사실 무방하다(현재 예시의 경우). 어처피 나머지 값은 전부 '0' 이고 실제 값은 하나 밖에 없어서 모두 더 해도 실제 값이 나오는 것이다. 무튼 이런식의 반복이 계속해서 진행되어 결국 음식종류에 대해 나이대 별 주문 수에 대한 결과 쿼리를 얻을 수 있는 것이다. 하...이걸 왜 '그렇구나' 하고 이해하는게 편하다고 했는지 도대체가 이해가 안된다. 오늘은 이걸로 시간을 좀 잡아 먹긴했지만 나름 원하는 답을 얻어 다행이다. 이것 외에도 WINDOWS FUNCTION 중 하나인 RANK 와 날짜/시간 데이터 포맷 및 형식을 다루는 DATE, DATE_FORMAT 에 대해 학습했다.

 

 

2. 과제

 알고리즘 및 SQL 코드카타를 진행하고 남은 SQL 개인 과제를 모두 진행하였다. 두 과제 모두 연습문제를 푸는 과제 였는데 해당 과제 모두 풀이를 적어 블로그에 남겨두었다. 아래의 항목을 클릭하면 해당 링크로 할 수 있다.

 

 

※ 참고 : 나는 TIL 작성 방식을 내가 학습하며 정리한 다른 게시글들과 하이퍼링크를 거는 방식으로 작성하였다. 학습한 내용에 하이퍼링크를 걸어두었으니 해당 링크를 통해 학습을 정리한 내용에 접근할 수 있다.