15일차

Suhyeon Lee·2024년 10월 22일
0

CodeKata

SQL

66. 조회수가 가장 많은 중고거래

  • 작성 쿼리
WITH temp AS (
  SELECT
    *
  FROM
    used_goods_board
  ORDER BY
    `views` DESC
  LIMIT 1
)

SELECT
  CONCAT('/home/grep/src/',f.board_id,'/',file_id,file_name,file_ext) AS file_path
FROM
  used_goods_file f
  JOIN temp t
  USING(board_id)
ORDER BY
  file_id DESC
;
SELECT
  CONCAT('/home/grep/src/',board_id,'/',file_id,file_name,file_ext) AS file_path
FROM
  used_goods_file 
WHERE
  board_id = (
    SELECT
      board_id
    FROM
      used_goods_board
    ORDER BY
      `views` DESC
    LIMIT 1  
  )
ORDER BY
  file_id DESC
;

조회수가 가장 높은 게시물은 하나만 존재합니다.라는 조건이 있어 이렇게 푼 거지 해당 조건 없으면 공동 1등일 경우도 고려해서 쿼리를 작성해야 한다고 생각함

참고할 만한 풀이

  • 2번 풀이 WHERE절을 MAX() 활용해 더 간단히 쓸 수 있음 → 스칼라 서브쿼리
FROM 
  USED_GOODS_BOARD B 
  JOIN USED_GOODS_FILE F
  ON B.BOARD_ID = F.BOARD_ID
WHERE
  B.VIEWS = (SELECT MAX(G.VIEWS) 
             FROM USED_GOODS_BOARD G)

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

  • 작성 쿼리
SELECT
  j.flavor
FROM
  july j
  JOIN first_half f
  ON j.flavor = f.flavor
GROUP BY
  j.flavor
ORDER BY
  SUM(j.total_order+f.total_order) DESC
LIMIT 3
;

→ 7월 strawberry(shipment_id 209)에 상반기 strawberry 3100이 중복으로 값이 들어가서 좋은 풀이가 아님

  1. UNION ALL
SELECT
  flavor
FROM (
  SELECT
    *
  FROM
    first_half
  UNION ALL
  SELECT
    *
  FROM
    july
  ) AS uni
GROUP BY
  flavor
ORDER BY
  SUM(total_order) DESC
LIMIT 3
;

→ UNION vs. UNION ALL

  • UNION (DISTINCT): 쿼리의 결과를 합친다. 중복된 ROW는 제거

  • UNION ALL: 모든 컬럼값이 같은 ROW도 결과로 보여준다. 중복제거 하지 않는다.

  • UNION ALL이 중복을 제거하지 않으므로 UNION 보다 속도가 빠름

  • UNION, UNION ALL은 그리 좋은 SQL 작성은 아님

    • 모델링 차원에서 테이블을 통합하는 게 좋음
  • 꼭 사용해야 한다면 UNION 보다는 UNION ALL 사용

    • UNION을 사용해야 한다면, 최소 필요 컬럼만 SELECT하기

참고할 만한 풀이

WITH JULY_F AS (SELECT FLAVOR, SUM(TOTAL_ORDER) AS TOTAL_ORDER
               FROM JULY GROUP BY FLAVOR)

SELECT A.FLAVOR
FROM (SELECT FH.FLAVOR, FH.TOTAL_ORDER + J.TOTAL_ORDER AS TOTAL FROM FIRST_HALF FH
LEFT JOIN JULY_F J ON FH.FLAVOR = J.FLAVOR
UNION
SELECT J.FLAVOR, FH.TOTAL_ORDER + J.TOTAL_ORDER AS TOTAL FROM FIRST_HALF FH
RIGHT JOIN JULY_F J ON FH.FLAVOR = J.FLAVOR) A
ORDER BY A.TOTAL DESC
LIMIT 3

→ FULL OUTER JOIN

SELECT F.FLAVOR
FROM FIRST_HALF F JOIN (SELECT FLAVOR, SUM(TOTAL_ORDER) TOTAL_ORDER
                        FROM JULY J 
                        GROUP BY FLAVOR) J ON F.FLAVOR = J.FLAVOR
GROUP BY FLAVOR
ORDER BY SUM(F.TOTAL_ORDER) + J.TOTAL_ORDER DESC
LIMIT 3

→ strawberry 중복 없이 만들어서 JOIN

문제 뜯어보기

  • first_half에서 flavor는 기본키(primary key)이므로 중복이 발행하지 않지만 july의 경우 flavor가 기본키가 아니라서 중복이 발행
    • 따라서 flavor 기준으로 JOIN하고 싶으면 july 테이블에서 flavor 기준 GROUP BY를 해 주어야 함
  • shipment_id 기준으로 INNER JOIN하면 안 되는 이유: july 테이블에서 shipment_id가 209인 strawberry 220가 사라짐
# 1. flavor 기준 INNER JOIN 활용
WITH temp AS (
  SELECT
    flavor
    , SUM(total_order) AS total_order
  FROM
    july
  GROUP BY
    flavor
),
temp2 AS (
  SELECT
    h.flavor
    , (h.total_order + t.total_order) AS total_order
  FROM
    first_half h
    JOIN temp t
    ON h.flavor = t.flavor
  ORDER BY
    total_order DESC
)
SELECT
  flavor
FROM
  temp2
LIMIT 3
;

# 2. shipment_id와 OUTER JOIN 활용
WITH temp AS (
  SELECT
    j.flavor
    , SUM(j.total_order+IFNULL(h.total_order, 0)) AS total_order
  FROM
    july j
    LEFT JOIN first_half h
    ON j.shipment_id = h.shipment_id
  GROUP BY
    j.flavor
  ORDER BY
    total_order DESC  
)
SELECT
  flavor
FROM
  temp
LIMIT 3
;

Python

18. 문자열을 정수로 바꾸기

  • 작성 코드
def solution(s):
    return int(s)

→ 출제 의도가 이건 아닌 것 같아서 다시 풀어봤음

def solution(s):
    answer = 0
    for idx, num in enumerate(s[::-1]):
        if num == '-':
            answer *= -1
        elif num == '+':
            continue
        else:
            answer += (ord(num) - ord('0')) * (10 ** idx)
    return answer

참고

참고할 만한 풀이

def strToInt(str):
    result = 0
    size=len(str)
    temp = 0
    if str [0] == '-' :
        sign = -1
    else :
        sign = 1
    for i in range(0, size) :
        if str[i] == '1' :
            temp = 1
        elif str[i] == '2' :
            temp = 2
        elif str[i] == '3' :
            temp = 3
        elif str[i] == '4' :
            temp = 4
        elif str[i] == '5' :
            temp = 5
        elif str[i] == '6' :
            temp = 6
        elif str[i] == '7' :
            temp = 7
        elif str[i] == '8' :
            temp = 8
        elif str[i] == '9' :
            temp = 9
        else :
            temp = 0
        for i in range(size-i-1) :
            temp = temp * 10
        result = result + temp
    result = result * sign
    return result

데이터 전처리 & 시각화

3주차
4주차

파이썬 개인 과제

profile
2 B R 0 2 B

0개의 댓글