티스토리 뷰

SQL 코드카타

Q133. Weather Observation Station 1

1. 문제 링크: https://www.hackerrank.com/challenges/weather-observation-station-1/problem

2. 정답 코드:

SELECT 
    CITY,
    STATE
FROM STATION;

 

Q146. Employee Names

1. 문제 링크: https://www.hackerrank.com/challenges/name-of-employees/problem

2. 정답 코드:

SELECT name
FROM Employee
ORDER BY name;

 

Q147. Employee Salaries

1. 문제 링크: https://www.hackerrank.com/challenges/salary-of-employees/problem

2. 정답 코드:

SELECT name
FROM Employee
WHERE salary > 2000
  AND months < 10
ORDER BY employee_id;

 

Q123. 176. Second Highest Salary

1. 문제 링크: https://leetcode.com/problems/second-highest-salary/description/

2. 정답 코드:

SELECT (
    SELECT MIN(salary)
    FROM (
        SELECT DISTINCT salary
        FROM Employee
        ORDER BY salary DESC
        LIMIT 2
    ) as s
    WHERE (
        SELECT COUNT(DISTINCT salary)
        FROM Employee
    ) > 1
) as SecondHighestSalary

3. 오류 상황: 데이터가 1개뿐이거나 모든 연봉이 같을 경우 아무런 행도 나오지 않음

4. 시도 방법: NULL 값으로 표현 가능한 방법이 뭔지 생성형 AI에게 힌트를 물어봄

5. 최종 문제 해결 방법:  단일 값을 반환하는 서브쿼리(스칼라 서브쿼리)를 마치 하나의 숫자나 글자처럼 취급해서 SELECT 바로 뒤에 붙여서 출력 → 해당하는 값이 없을 때는 NULL 출력


 

스칼라 서브쿼리를 사용하는 이유?

가장 큰 이유는 결과가 없을 때 NULL을 받아내기 위해서!

  1. 일반 쿼리 (FROM 포함) : SELECT salary FROM Employee WHERE ... 만약 조건에 맞는 데이터가 없으면? 그냥 아무것도 없는 빈 결과(Empty set)가 나옴
  2. 스칼라 서브쿼리 : SELECT (SELECT salary FROM Employee WHERE ...) AS SecondHighestSalary 조건에 맞는 데이터가 없으면? 쿼리 전체가 NULL이라는 값 하나를 결과로 딱 보여줌
SELECT salary as SecondHighestSalary
FROM Employee
WHERE salary IN (
    SELECT MIN(salary)
    FROM (
        SELECT DISTINCT salary
        FROM Employee
        ORDER BY salary DESC
        LIMIT 2
    ) as s
)
  AND salary NOT IN (
    SELECT MAX(salary)
    FROM Employee
  )

# 이전에 작성했던 쿼리

 

Q124. 1484. Group Sold Products By The Date

1. 문제 링크: https://leetcode.com/problems/group-sold-products-by-the-date/description/

2. 정답 코드:

SELECT
    sell_date,
    COUNT(DISTINCT product) as num_sold,
    GROUP_CONCAT(DISTINCT product ORDER BY product) as products
FROM Activities
GROUP BY sell_date
ORDER BY sell_date

3. 오류 상황: 그룹으로 묶어서 해당되는 행 값들을 한번에 컬럼으로 합치는 방법을 모름

4. 시도 방법: 구현할 수 있는 함수가 있는지 알기 위해 생성형 AI에게 물어봄

5. 최종 문제 해결 방법: GROUP_CONCAT 사용해서 문제 풀이


GROUP_CONCAT 함수

이름 그대로 그룹(GROUP)으로 묶어서, 문자열을 연결(CONCAT)해주는 함수! → GROUP BY와 함께 사용

 

사용 방법

만약 테이블 이름이 Sales이고, sale_date(날짜)와 product(물건) 컬럼이 있다면 아래와 같이 작성한다

SELECT
    sale_date, 
    GROUP_CONCAT(product) AS products_list
FROM Sales
GROUP BY sale_date;

 

더 깔끔하게 만드는 꿀팁

그냥 묶기만 하면 순서가 뒤죽박죽이거나 중복된 이름이 나올 수 있는데, 이럴 때 함수 안에 옵션을 추가할 수 있다

  • 중복 제거: 같은 날 같은 물건이 여러 번 팔렸을 때 한 번만 나오게 하려면 DISTINCT 추가
  • 정렬: 가나다 순으로 정렬하고 싶다면 ORDER BY 추가
  • 구분자 변경: 쉼표(,) 말고 슬래시(/)나 공백으로 연결하고 싶다면 SEPARATOR 추가
예시)
SELECT
    sale_date, 
    GROUP_CONCAT(DISTINCT product ORDER BY product ASC SEPARATOR ', ') AS products_list
FROM Sales
GROUP BY sale_date;

Python 코드카타 (https://github.com/heeso0908/codekata.git)

Q44. 최소직사각형 ★★★

1. 문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/86491

2. 정답 코드:

def solution(sizes):
    max_w = 0
    max_h = 0
    for s in sizes:
        a = max(s[0], s[1])
        b = min(s[0], s[1])
        
        if a > max_w:
            max_w = a
        if b > max_h:
            max_h = b

    return max_w * max_h
수도코드 작성부터 이해가 되지 않고, 평소에 생각해보지 못했던 유형이라 매우 어려웠다,, 시간을 오래 들여도 마땅한 해결 방법이 떠오르지 않아 생성형 AI에게 도움을 요청했다ㅠㅡㅠ

📋 명함 지갑 크기 줄이기: "가장 긴 놈을 한곳으로 몰아라!"

1. 문제 상황: "명함이 제각각이야!"

가로가 긴 명함, 세로가 긴 명함... 모양이 제각각인 명함들을 하나의 지갑에 쏙 넣으려고 한다. 지갑 크기를 최소로 만들려면 어떻게 해야 할까?

  • 명함 A: 가로 60, 세로 50
  • 명함 B: 가로 30, 세로 70

그냥 넣으면 가로는 최소 60, 세로는 최소 70이어야 해서 지갑 크기는 60 × 70 = 4200이 된다. 하지만 명함을 회전시킬 수 있다면 어떨까?

 

2. 핵심 전략: "긴 쪽을 가로로 통일하기"

명함을 가로로 눕히든 세로로 세우든 상관없다는 게 포인트! 지갑을 가장 작게 만드는 비법은 딱 하나

"모든 명함을 돌려서, 더 긴 변을 가로(w)로, 더 짧은 변을 세로(h)로 몰아넣는 것!"

이렇게 하면 한쪽으로 큰 숫자들을 다 모을 수 있어서, 지갑의 가로세로를 낭비 없이 결정할 수 있다!

 

3. 수학으로 이해하기 (알고리즘 흐름)

  1. 명함 돌리기: 각 명함의 (가로, 세로) 중에서 큰 숫자를 무조건 w로, 작은 숫자를 무조건 h로 정함
  2. 최종 가로 정하기: 그렇게 정해진 w들 중에서 가장 큰 값을 찾기 (그래야 모든 명함이 가로로 들어감)
  3. 최종 세로 정하기: 그렇게 정해진 h들 중에서 가장 큰 값을 찾기 (그래야 모든 명함이 세로로 들어감)

4. 파이썬 코드로 구현하기

def solution(sizes):
    # 가장 큰 가로와 세로를 저장할 변수 (0으로 시작)
    max_w = 0
    max_h = 0
    
    for s in sizes:
        # s[0]은 가로, s[1]은 세로
        # 둘 중 큰 값을 a, 작은 값을 b라고 하자 (명함 회전!)
        a = max(s[0], s[1])
        b = min(s[0], s[1])
        
        # 지금까지 본 가로(a) 중 제일 큰 놈을 지갑 가로로!
        if a > max_w:
            max_w = a
            
        # 지금까지 본 세로(b) 중 제일 큰 놈을 지갑 세로로!
        if b > max_h:
            max_h = b
            
    # 지갑의 넓이 = 가로 x 세로
    return max_w * max_h

 

5. 한 줄 요약!

명함을 가로/세로 구분 말고 [큰 값, 작은 값]으로 정렬한 뒤, 큰 값들 중의 왕과 작은 값들 중의 왕을 곱하면 끝!
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함