Sparta/CODEKATA

[250826] 스파르타코딩 본캠프 16일차 - 도전과제

junecho 2025. 8. 26. 21:36

💥  CODEKATA                                                                                                           

~ 70문제

 

오늘 집중이 너무 안되는 날이었음…

 

 

 

 

66) 조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기

SELECT
    CONCAT("/home/grep/src/", uf.board_id, "/", uf.file_id, uf.file_name, uf.file_ext) AS file_path
FROM 
    used_goods_file uf 
    JOIN (
        SELECT board_id
        FROM used_goods_board
        WHERE views = ( SELECT MAX(views) FROM used_goods_board)) ub 
    ON uf.board_id = ub.board_id
ORDER BY
    uf.file_id DESC

 

 

 

 

67) 주문량이 많은 아이스크림들 조회하기

SELECT 
    a.flavor
FROM (
    SELECT
        j.shipment_id, f.flavor, 
        SUM(f.total_order) sumfirst,
        SUM(j.total_order) sumjuly,
        SUM(f.total_order) + SUM(j.total_order) AS sum_total
    FROM
        first_half f LEFT JOIN july j ON f.flavor = j.flavor
    GROUP BY
        f.flavor
    ORDER BY
        sum_total DESC
    ) a LIMIT 3

 

 

 

 

68) 저자 별 카테고리 별 매출액 집계하기

# 1차 코드
    SELECT 
        s.book_id, SUM(s.sales) sum_sales, b.author_id, b.category, b.price,
        (SUM(s.sales) * b.price) AS total_sales
    FROM
        book_sales s JOIN book b ON s.book_id = b.book_id
    WHERE
        s.sales_date LIKE "2022-01-%"
    GROUP BY
        s.book_id

⇒ book_id 별로 총 매출액은 구했는데, 이제 저자가 같으면서 카테고리도 같은 컬럼의 total_sales를 더해야 함.

# 2차 코드
WITH total AS (
    SELECT 
        s.book_id, b.author_id, b.category,
        (SUM(s.sales) * b.price) AS sumprice
    FROM
        book_sales s JOIN book b ON s.book_id = b.book_id
    WHERE
        s.sales_date LIKE "2022-01-%"
    GROUP BY
        s.book_id
)

SELECT 
    a.author_id, a.author_name, t.category, 
    SUM(t.sumprice) as total_sales 
FROM 
    author a LEFT JOIN total t ON a.author_id = t.author_id
GROUP BY
    1, 2, 3
ORDER BY
    a.author_id,
    t.category DESC

⇒ 처음에 GROUP BY 를 t.category 만 했다가 아차차 하고 1,2,3 다 넣어버림

 

 

 

 

69) 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기

# 1차 코드
WITH fivecnt AS (
    SELECT
        car_id, count(car_id) as totalcnt
    FROM 
        car_rental_company_rental_history
    WHERE
        start_date LIKE "2022-08-%" OR 
        start_date LIKE "2022-09-%" OR 
        start_date LIKE "2022-10-%"
    GROUP BY
        car_id
    HAVING 
        count(car_id) >= 5
)

SELECT 
    DATE_FORMAT(h.start_date, "%m") as month,
    f.car_id,
    count(DATE_FORMAT(h.start_date, "%m")) records
FROM car_rental_company_rental_history h JOIN fivecnt f ON h.car_id = f.car_id
GROUP BY
    1,2
ORDER BY
    month, car_id DESC

음 결과 맞는 것 같은데 왜 틀렸다 하지

아 DATE_FORMAT() 으로 뽑으면 08월 이렇게 나오는데, 출력 결과에선 그냥 8 으로 되어있음.

그래서 MONTH() 사용으로 수정. LIKE도 BETWEEN으로 수정.

그리고 굳이 JOIN 안해도 될 것 같은데?

본문 절에서 날짜 제한 안했더니 다른놈들이 또 튀어나와서 틀린거였음. WITH를 빼자니 총 5번 렌탈한 결과가 안나오고 월 별로 5번 이상 구매한 놈들만 나옴…ㄱ- 두 번이나 써야 되나…?

# 2차 코드
# join 빼는 건 지피티의 도움을 받아서 where in 으로 처리하는걸 깨달음
WITH fivecnt AS (
    SELECT
        car_id
    FROM 
        car_rental_company_rental_history
    WHERE
        start_date BETWEEN "2022-08-01" AND "2022-10-31"
    GROUP BY
        car_id
    HAVING 
        count(car_id) >= 5
)

SELECT 
    MONTH(start_date) as month,
    car_id,
    count(1) records
FROM 
    car_rental_company_rental_history
WHERE
    start_date BETWEEN "2022-08-01" AND "2022-10-31" AND
    car_id IN (SELECT car_id FROM fivecnt)
GROUP BY
    1, 2
ORDER BY
    month, car_id DESC

 

 

 

 

70) 그룹별 조건에 맞는 식당 목록 출력하기

WITH max_review_count AS (
    SELECT MAX(cnt) AS max_cnt
    FROM (
        SELECT member_id, COUNT(*) AS cnt
        FROM rest_review
        GROUP BY member_id
    ) AS counts
)

SELECT 
    m.member_name, r.review_text, DATE_FORMAT(r.review_date, '%Y-%m-%d') AS review_date
FROM 
    rest_review r JOIN member_profile m ON r.member_id = m.member_id
WHERE 
    r.member_id IN (
        SELECT member_id
        FROM rest_review
        GROUP BY member_id
        HAVING COUNT(*) = (SELECT max_cnt FROM max_review_count)
    )
ORDER BY 
    r.review_date, r.review_text

WITH 절로 리뷰수 제일 많은 MAX(member_id)의 갯수를 구하고,

본문 절 WHERE 에서 member_id 를 선택하는데, 기준이 MAX(member_id)인 id만 선택.

뭔가 너무 너지저분한 것 같은데 이게 최선인가…?

이 문제 이실직고. 풀다가 오늘 집중 너무 안돼서 문명의 도움을 좀 받음 ㅎㅎ…..나중에 다시 풀어봐야지

 

 


🔰 과제                                                                                                  

개인과제 - 도전

더보기
더보기
문제 6 : 두 수의 합(인덱스 반환)


📌 요구 지식: 딕셔너리, 반복문, 조건문
배경:
목표 합을 만드는 두 원소의 인덱스를 빠르게 찾는 패턴 연습입니다.

목표:
정수 리스트 nums와 정수 target이 주어질 때, 합이 target이 되는 서로 다른 두 인덱스를 (i, j)로 반환하세요. (없으면 (-1, -1))


데이터:
# ex1. 반환 값 (0,1)
nums = [2, 7, 11, 15]
target = 9

# ex2. 반환 값 (-1, -1)
nums = [2, 7, 11, 15]
target = 10
​
def two_sum(nums, target):
    """
    반환값 예: (0, 1)  # nums[0] + nums[1] = 9
    """
    # 여기에 코드를 작성하세요
    return

# 예시 실행 (제출 시 주석 처리)
# print(two_sum(nums, target))

# %%
'''
nums1 = [2, 7, 11, 15]
target1 = 9

nums2 = [2, 7, 11, 15]
target2 = 10

nums3 = [7, 11, 15, 2]
target3 = 9
'''
def two_sum(nums, target):
    result = ()
    result2 = ()
    for i in range(len(nums)):
        for j in range(len(nums)):
            if nums[i] + nums[j] == target:
                result = (j, i)
            else:
                result2 = (-1, -1)
    if len(result) >= 2:
        return result
    else:
        return result2
    
# print(two_sum(nums1, target1))  # (0, 1)
# print(two_sum(nums2, target2))  # (-1, -1)
# print(two_sum(nums3, target3))  # (0, 3)


# %%
문제 7 : 이동 평균 구하기(슬라이딩 윈도우)

📌 요구 지식: 리스트, 반복문, 누적합(슬라이딩 윈도우)
배경:
시계열에서 일정 구간의 평균을 구해 노이즈를 줄입니다.
목표:
정수 리스트 data와 윈도우 크기 k가 주어질 때, 길이 k의 구간 평균 리스트를 반환하세요. (각 평균은 소수 둘째 자리 반올림)

데이터:
data = [10, 20, 30, 40, 50]
k = 3
​
def moving_average(data, k):
    """
    반환값 예: [20.0, 30.0, 40.0]
    """
    # 여기에 코드를 작성하세요
    return

# 예시 실행 (제출 시 주석 처리)
# print(moving_average(data, k))  # [20.0, 30.0, 40.0]

# %%
def moving_average(data, k):
    result = []
    lendata = len(data)
    if k > 0:
        for i in range(0, lendata-k+1):
            x = sum(data[:k]) / k
            result.append(x)
            data.pop(0)
        return result
    else:
        result = []
        return result

# %%
문제 8 : 숫자 구간 압축하기

📌 요구 지식: 리스트, 반복문, 조건문, 문자열 조합
문제배경
로그의 라인 번호나 주문 ID처럼 연속된 숫자 구간을 짧게 표현합니다.

목표
오름차순 정렬된 서로 다른 정수 리스트가 주어졌을 때, 연속 구간은 a-b, 단일 값은 a로 표현하여 ","로 연결한 문자열을 반환하세요.
예)
[1,2,3,5,7,8,9] → "1-3,5,7-9"
[1,3,5,7,9]-> "1,3,5,7,9"
​
제한사항
입력 리스트는 오름차순이며 중복이 없습니다.
데이터:
nums = [1, 2, 3, 5, 7, 8, 9]
​
def compress_ranges(nums):
    """
    반환값 예: "1-3,5,7-9"
    """
    # 여기에 코드를 작성하세요
    return

# 예시 실행 (제출 시 주석 처리)
# print(compress_ranges(nums))  # "1-3,5,7-9"

# %%
def compress_ranges(nums):
    leng = len(nums)    # 7
    result_list = []
    no_duplication = set()

    for i in range(leng):
        if nums[i] in no_duplication:
            continue

        start_idx = i
        end_idx = i
        stop = True

        for j in range(1, leng):
            if i + j >= leng:
                break
            elif nums[i + j] == nums[i] + j:
                end_idx = i + j
                stop = False
            else:
                break

        if stop:
            result_list.append(str(nums[i]))
        else:
            result_list.append(f"{nums[start_idx]}-{nums[end_idx]}")

        for k in range(start_idx, end_idx + 1):
            no_duplication.add(nums[k])

    result = ",".join(result_list)
    return result