Skip to content
CatBus

Posts

All the articles I've posted.

PROGRAMMERS284531SQL
SELECT route,
    CONCAT(ROUND(SUM(d_between_dist), 1), 'km') AS total_distance,
    CONCAT(ROUND(AVG(d_between_dist), 2), 'km') AS average_distance
FROM subway_distance
GROUP BY route
ORDER BY ROUND(SUM(d_between_dist), 1) DESC;

-- SELECT route,
--     CONCAT(ROUND(SUM(d_between_dist), 1), 'km') AS total_distance,
--     CONCAT(ROUND(AVG(d_between_dist), 2), 'km') AS average_distance
-- FROM subway_distance
-- GROUP BY route
-- ORDER BY total_distance DESC;

문제에서 요구한 결과를 만들기 위해 쿼리에서 실제로 쓴 것들이다.

노선별 평균 역 사이 거리 조회하기

노선별로 SUM 과 AVG 를 각각 구해 ROUND 자릿수를 다르게 주고, CONCAT 으로 'km' 를 붙여 문자열로 만든다.

2025.07.17·1분·sql
PROGRAMMERS157339SQL
WITH cars_with_fee AS (
    SELECT
        c.car_id,
        c.car_type,
        FLOOR(c.daily_fee * 30 * (100 - p.discount_rate) / 100) AS fee
    FROM
        car_rental_company_car AS c
    JOIN
        car_rental_company_discount_plan AS p ON c.car_type = p.car_type
    WHERE
        c.car_type IN ('세단', 'SUV')
        AND p.duration_type = '30일 이상'
)
SELECT
    car_id,
    car_type,
    fee
FROM
    cars_with_fee
WHERE
    car_id NOT IN (
        SELECT
            car_id
        FROM
            car_rental_company_rental_history
        WHERE
            end_date >= '2022-11-01' AND start_date <= '2022-11-30'
    )
    AND fee >= 500000 AND fee < 2000000
ORDER BY
    fee DESC,
    car_type ASC,
    car_id DESC;

특정 기간동안 대여 가능한 자동차들의 대여비용 구하기

CTE 에서 30일 요금제 할인율을 FLOOR 로 적용해 두고, 해당 기간에 대여 기록이 겹치는 차를 NOT IN 으로 걸러 낸다.

2025.07.10·2분·sql
PROGRAMMERS131533SQL
SELECT pd.product_code, SUM(os.sales_amount) * pd.price as sales
FROM product as pd
    JOIN
    offline_sale as os
    ON pd.product_id = os.product_id
GROUP BY pd.product_id
ORDER BY sales DESC, pd.product_code ASC

문제에서 요구한 결과를 만들기 위해 쿼리에서 실제로 쓴 것들이다.

  • 테이블 1회 JOIN 으로 두 테이블을 연결
  • GROUP BY 로 묶어서 집계
  • ORDER BY 로 정렬 (내림차순 포함)
  • 사용한 함수: SUM()

상품 별 오프라인 매출 구하기

상품과 오프라인 판매를 조인해 SUM(수량) × 단가로 매출을 만든다. GROUP BY 는 product_id 로 하고 정렬만 product_code 를 쓴다.

2025.07.10·1분·sql
BOJ2313GOLD 5
INF = float('inf')

n = int(input())

total_sum = 0
select_idx = []
for _ in range(n):
    L = int(input())
    jewels = list(map(int, input().split()))

    cum_sum = [0] * (L + 1)
    for i in range(1, L + 1):
        cum_sum[i] += cum_sum[i - 1] + jewels[i - 1]
    
    max_sum = -INF
    max_start = 1
    max_end = L

    for k in range(L, 0, -1):
        is_max = False
        for i in range(0, L - k + 1):
            part_sum = cum_sum[k + i] - cum_sum[i]
            if max_sum > part_sum:
                continue
            # 최대값과 같고 이미 앞에서 그 값이 나온 경우
            elif max_sum == part_sum and is_max:
                continue

            max_sum = part_sum
            max_start = i + 1
            max_end = k + i
            is_max = True
    total_sum += max_sum
    select_idx.append((max_start, max_end))


print(total_sum)
for result in select_idx:
    print(*result)

보석 구매하기

백준 2313번 '보석 구매하기' (골드 5) 문제 풀이. dynamic programming, prefix sum, traceback 로 접근했다.

2025.07.10·2분·dynamic programming
BOJ1874SILVER 2
cur_num = 2
stack = [1]
result = ['+']
for _ in range(n):
    target = int(input())
    if not stack:
        stack.append(cur_num)
        result.append('+')
        cur_num += 1
    while stack and stack[-1] < target:
        stack.append(cur_num)
        result.append('+')
        cur_num += 1
    if stack and stack[-1] == target:
        stack.pop()
        result.append('-')
        continue

if len(stack) == 0:
    print(*result, sep='\n')
else:
    print('NO')

스택 수열

백준 1874번 '스택 수열' (실버 2) 문제 풀이. data structures, stack 로 접근했다.

2025.07.10·2분·data structures
BOJ18404SILVER 1
N, M = map(int, input().split())

dxy = ((1, 2), (2, 1), (-1, 2), (2, -1), (1, -2), (-2, 1), (-1, -2), (-2, -1))

x, y = map(int, input().split())

enemy_list = [tuple(map(int, input().split())) for _ in range(M)]
result = [0] * M

q = deque([(x, y, 1)])
find_cnt = 0
visited = set([(x, y)])

while q:
    cur_x, cur_y, t = q.popleft()

    for dx, dy in dxy:
        n_x, n_y = cur_x + dx, cur_y + dy
        if (n_x, n_y) in visited:
            continue
        if (n_x, n_y) in enemy_list:
            enemy_idx = enemy_list.index((n_x, n_y))
            if result[enemy_idx] != 0:
                continue
            result[enemy_idx] = t
            find_cnt += 1
        if find_cnt == M:
            break
        q.append((n_x, n_y, t + 1))
        visited.add((n_x, n_y))
    else:
        continue
    break

print(*result)

현명한 나이트

백준 18404번 '현명한 나이트' (실버 1) 문제 풀이. graph theory, graph traversal, bfs 로 접근했다.

2025.07.03·2분·graph theory
PROGRAMMERS284528SQL
-- 사번, 성명, 평가 등급, 성과금
-- 부서 정보
-- 사원 정보
-- 사원 평가 정보
WITH avg_emp AS (
    SELECT he.emp_no, he.emp_name, he.sal,
        CASE
            WHEN AVG(hg.score) >= 96 THEN 'S'
            WHEN AVG(hg.score) >= 90 THEN 'A'
            WHEN AVG(hg.score) >= 80 THEN 'B'
            ELSE 'C'
    END AS grade
    FROM hr_employees AS he
        LEFT JOIN
        hr_grade AS hg
        ON he.emp_no = hg.emp_no
    GROUP BY he.emp_no
)

SELECT emp_no, emp_name, grade,
    CASE
        WHEN grade = 'S' THEN sal * 0.2
        WHEN grade = 'A' THEN sal * 0.15
        WHEN grade = 'B' THEN sal * 0.1
        WHEN grade = 'C' THEN 0
        ELSE NULL
    END AS bonus
FROM avg_emp
ORDER BY emp_no

연간 평가점수에 해당하는 평가 등급 및 성과금 조회하기

CTE 에서 사원별 평균 점수를 CASE 로 S·A·B·C 등급으로 바꾸고, 바깥에서 등급별 지급률을 다시 CASE 로 적용해 성과금을 구한다.

2025.07.03·2분·sql
PROGRAMMERS299308SQL
WITH quarter AS (
    SELECT 
        CASE
            WHEN(QUARTER(differentiation_date)) = 1 THEN '1Q'
            WHEN(QUARTER(differentiation_date)) = 2 THEN '2Q'
            WHEN(QUARTER(differentiation_date)) = 3 THEN '3Q'
            WHEN(QUARTER(differentiation_date)) = 4 THEN '4Q'
            ELSE NULL
    END AS quarter
    FROM ecoli_data
)

SELECT quarter, COUNT(*) AS ecoli_count
FROM quarter
GROUP BY quarter
ORDER BY quarter

문제에서 요구한 결과를 만들기 위해 쿼리에서 실제로 쓴 것들이다.

분기별 분화된 대장균의 개체 수 구하기

QUARTER() 로 분화일을 분기 문자열로 바꾸는 CTE 를 만들고, 바깥에서 그 값으로 GROUP BY 해 분기별 개체 수를 센다.

2025.07.03·1분·sql
BOJ1241GOLD 5
from collections import Counter, defaultdict

input = sys.stdin.readline
print = sys.stdout.write

N = int(input())

students = [int(input()) for _ in range(N)]
MAX_STUDENT = max(students) + 1

counter = Counter(students)
toktok = defaultdict(int)

for i in range(1, MAX_STUDENT):
    for j in range(i, MAX_STUDENT, i):
        if j in counter:
            toktok[j] += counter[i]

print("\n".join(str(toktok[s] - 1) for s in students) + "\n")

머리 톡톡

백준 1241번 '머리 톡톡' (골드 5) 문제 풀이. math, number theory, primality test 로 접근했다.

2025.07.03·1분·math