240511_TIL

J Lee·2024년 5월 11일
0

아무리 사소하더라도 배움이 없는 날은 없다.

SQL코드카타 112번
case when을 써서 집계 기준을 잡아주고 group by로 집계까지 했는데 해당하는 값이 없을 경우를 어떻게 다룰지 묻는 문제.

먼저 문제에서 요구한 조건대로 low, average, high salary를 집계해 보면

select case when income < 20000 then 'Low Salary'
            when income between 20000 and 50000 then 'Average Salary'
            when income > 50000 then 'High Salary' end as category,
        count(account_id) as count
from Accounts
group by 1

결과가 이렇게 나온다.

average에 해당하는 값이 테이블에 없었기 때문에 아예 분류조차 되지 않은 것. 그러나 문제에서는 없는 경우도 0으로 세서 출력하라고 했으므로 다른 조치가 필요하다.

이럴 경우에는 아예
① low, average, high 등 커버해야 할 모든 케이스를 빈 껍데기 row로만 만들어 두고
② 실제 집계한 결과를 left join 시키면 해결할 수 있다.

먼저 ①을 만들어 보면

(select 'Low Salary' as category
union
select 'Average Salary' as category
union
select 'High Salary' as category) a


실제 테이블에서 뭘 불러올 건 아니므로 from절 이하는 없어도 되고, 빈 row만 불러준 다음에 수직 결합(union)해 주면 껍데기가 만들어진다.

이제 이 빈 껍데기와 위에서 구한 실제 집계 결과를 left join해 준다.

SELECT a.category,
       Ifnull(count, 0) AS accounts_count
FROM   (SELECT 'Low Salary' AS category
        UNION
        SELECT 'Average Salary' AS category
        UNION
        SELECT 'High Salary' AS category) a
       LEFT JOIN (SELECT CASE
                           WHEN income < 20000 THEN 'Low Salary'
                           WHEN income BETWEEN 20000 AND 50000 THEN
                           'Average Salary'
                           WHEN income > 50000 THEN 'High Salary'
                         end               AS category,
                         Count(account_id) AS count
                  FROM   accounts
                  GROUP  BY 1) b
              ON a.category = b.category 

join의 결과 데이터가 없는 average salary는 null로 뜰 것이므로, 본 쿼리에서는 ifnull을 활용해 0으로 바꿔 출력해 준다.

이번 문제는 실무를 하면서 마주쳤던 상황과 똑같았다. 당시에는 이런 쿼리 스킬을 몰라서 집계된 값만 불러오고 나머지는 엑셀이나 스프레드시트에서 0으로 수기 입력했다. 껍데기만 만들어놓고 조인하는 이 방법이 앞으로도 요긴하게 잘 쓰일 듯.


알고리즘 코드카타 37번
행렬의 덧셈 문제.

행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해주세요.

arr1 = [[1,2],[2,3]]
arr2 = [[3,4],[5,6]]
결과 = [[4,6],[7,9]]

zip을 써서 풀어보려고 고민했지만 아직 실력이 딸려서 실패.

행렬은 행과 열이 모두 있기 때문에 for문을 이중으로 중첩해서 써야 했다. 중첩에 대한 그림이 머릿속에 잘 그려지지 않아서 어렵게 느껴진 듯.

def solution(arr1, arr2):
    x = []
    for i in range(len(arr1)):
        temp = []
        for j in range(len(arr1[i])):
            temp.append(arr1[i][j]+arr2[i][j])
        x.append(temp)
    return x

안쪽의 반복문부터 하나씩 살펴보면 (작은 단위 → 큰 단위)

        temp = []
        for j in range(len(arr1[i])):
            temp.append(arr1[i][j]+arr2[i][j])

이 반복문에 의해 j는 0부터 arr1[i]의 길이, 즉 행의 길이만큼 반복된다. 반복문 안에 temp라는 임시 리스트를 선언해 두고 반복문의 결과를 temp에 담는다. 그 결과,

  • arr1[i][0]+arr2[i][0]
  • arr1[i][1]+arr2[i][1]

이렇게 두 개 요소가 ,로 엮여서 temp에 담기게 된다.

    x = []
    for i in range(len(arr1)):
        temp = []
        for j in range(len(arr1[i])):
            temp.append(arr1[i][j]+arr2[i][j])
        x.append(temp)

다시 메인 코드에서 빈 리스트 x를 선언해 두고 이번에는 i에 대해 같은 연산을 반복해 준다. 그 결과,

  • arr1[0][0]+arr2[0][0]
  • arr1[0][1]+arr2[0][1]
  • arr1[1][0]+arr2[1][0]
  • arr1[1][1]+arr2[1][1]

이렇게 네 개의 요소가 (temp가 리스트이므로) 리스트 형태로 둘씩 짝지어서 x에 담기게 된다.

1) 계산하는 방법
2) 계산한 결과를 어떻게 담아서 출력할지

를 모두 고민해야 하는 문제였다. 사실 연습장에 손으로 써 가면서 하나씩 써 가면서 만들었는데, 아직은 머릿속으로 논리를 따라가지 못해서 손의 도움을 받아야 한다...ㅎㅎ

놓치지만 않으면 되는 날이 오겠지. 연습만이 살길이다 진짜.

profile
기본기를 소홀히 하지 말자

0개의 댓글