Today I Learned

231214 / 프로그래머스 예제 풀이

sance 2023. 12. 14. 21:57
SQL 예제 풀이

 

48. REST_INFO 테이블에서 음식종류별로 즐겨찾기수가 가장 많은 식당의 음식 종류, ID, 식당 이름, 즐겨찾기수를 조회하는 SQL문을 작성해주세요. 이때 결과는 음식 종류를 기준으로 내림차순 정렬해주세요.

 

처음에는 단순히 아래와 같은 쿼리문을 작성했는데 일식당의 결과가 틀린 것으로 나왔다.

음식종류별 즐겨찾기수 최대치를 서브쿼리로 만들어서 사용해야 할 것 같은데 어느 부분에 적용해야할지 감이 안와 다른 사람의 정답을 참고한 결과 WHERE문에서 IN 서브쿼리를 사용하는 답을 찾았다. 

#오답
select FOOD_TYPE, REST_ID, REST_NAME, max(FAVORITES)
from REST_INFO
group by 1
order by 1 desc

 

음식종류별 최대 즐겨찾기수를 서브쿼리로 만들어준 뒤 조건문 WHERE IN 연산자에 사용해주었다. 

두번째 GROUP BY가 왜 필요한가 생각해봤는데 하지 않으면 일식의 max_FAVORITES 값과 동일한 한식당이 결과로 추가되기 때문이다.

select FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
from REST_INFO
where FAVORITES in (select max(FAVORITES) from REST_INFO group by FOOD_TYPE)
group by 1
order by 1 desc

 

다음과 같이 서브쿼리를 JOIN으로 사용해주는 방법도 있다.

select i.FOOD_TYPE, i.REST_ID, i.REST_NAME, f.FAVORITES
from REST_INFO i
inner join (select FOOD_TYPE, max(FAVORITES) FAVORITES
                 from REST_INFO group by 1) f on i.FAVORITES=f.FAVORITES
group by 1
order by 1 desc

 

 

53. ONLINE_SALE 테이블에서 동일한 회원이 동일한 상품을 재구매한 데이터를 구하여, 재구매한 회원 ID와 재구매한 상품 ID를 출력하는 SQL문을 작성해주세요. 결과는 회원 ID를 기준으로 오름차순 정렬해주시고 회원 ID가 같다면 상품 ID를 기준으로 내림차순 정렬해주세요.

 

동일 회원이 동일 상품을 재구매한 경우이므로 먼저 회원을 기준으로 그룹을 묶고 다음으로 상품 ID를 기준으로 그룹화하여 회원마다 어떠한 상품을 구매했는지 그룹화해주었다. 이 그룹을 기준으로 HAVING 조건문을 동일 제품을 2회 이상 구매한 경우로 카운트했다.

select user_id, product_id
from ONLINE_SALE
group by user_id, product_id
having count(product_id)>=2
order by 1, 2 desc

 

 

55. USED_GOODS_BOARD와 USED_GOODS_USER 테이블에서 중고 거래 게시물을 3건 이상 등록한 사용자의 사용자 ID, 닉네임, 전체주소, 전화번호를 조회하는 SQL문을 작성해주세요. 이때, 전체 주소는 시, 도로명 주소, 상세 주소가 함께 출력되도록 해주시고, 전화번호의 경우 xxx-xxxx-xxxx 같은 형태로 하이픈 문자열(-)을 삽입하여 출력해주세요. 결과는 회원 ID를 기준으로 내림차순 정렬해주세요.

 

이번 문제에서는 여러 컬럼을 합쳐서 하나의 컬럼으로 만들고 데이터를 원하는 형태로 바꾸는 함수가 필요하기 때문에 CONCAT과 SUBSTR을 사용했다. 문제 풀이에 더 적절한 함수가 있을까하고 다른 사람의 정답도 살펴봤는데 CONCAT_WS 함수를 사용하는 풀이가 있었다. 이를 사용하면 다음과 같은 코드 작성이 가능하다. * concat_ws(' ', u.city, u.street_address1, u.street_address2)

또, SUBSTR과 비슷한 기능으로 LEFT, MID, RIGHT 함수 사용이 가능하다.

 

CONCAT_WS 문자열을 특정 구분자로 합치기 concat_ws('구분자', 문자열, 문자열, ...)
LEFT 왼쪽을 기준으로 문자를 일정 갯수 가져오기 left(문자, 가져올 갯수)
MID SUBSTR 함수와 동일 mid(문자, 시작 위치, 가져올 갯수)
RIGHT 오른쪽을 기준으로 문자를 일정 갯수 가져오기 right(문자, 가져올 갯수)
select u.user_id, u.nickname,
           concat(u.city, ' ', u.street_address1, ' ', u.street_address2) "전체주소",
           concat(substr(u.tlno,1,3), '-', substr(u.tlno,4,4), '-', substr(u.tlno,8,4)) "전화번호"
from used_goods_board b left join used_goods_user u on b.writer_id=u.user_id
group by 1
having count(*)>=3
order by 1 desc

 

 

Python 예제 풀이

 

13. 자연수 N이 주어지면, N의 각 자릿수의 합을 구해서  return하는 solution 함수를 만들어 주세요. 예를 들어 N=123이면 1+2+3=6을 return하면 됩니다. (*N의 범위 : 100,000,000 이하의 자연수)

 

숫자를 STR 문자형으로 바꿔준 뒤 각 자릿수를 다시 정수형으로 바꿔 더해주는 반복문을 사용한다. 

def solution(n):
      answer = 0 
      for i in str(n):
           answer += int(i)
      return answer

 

 

14. 정수 N을 입력받아 N의 약수를 모두 더한 값을 리턴하는 solution 함수를 완성해주세요. (*N은 0 이상 3,000 이하인 정수)

 

이번 문제는 약수를 구하는 수학 문제로 볼 수 있다.

RANGE함수와 반복문을 사용해 N을 1부터 N까지의 숫자으로 하나씩 나눠보고 나머지가 0인 숫자만 모두 더해주었다.

def solution(n):
      answer = 0
      for i in range(1,n+1):
            if(n%i==0):
                 answer+=i
      return answer