Data_10기

Python Standard (표준화 vs 정규화) 및 SQL 코드카타

senu 2025. 12. 8. 21:12

오늘은 월요일이라 그런지 너무 피곤했다. 라이브 세션도 4개나 돼서 그런지 정신도 없었다. 그래서 그런지 책상 앞에 앉은 시간에 비해 공부를 많이 하진 못한 날이다. 그래도 오늘 짚고 넘어가고 싶은 내용들에 대해서 TIL로 정리해 보았다.


Ⅰ. Python Standard - 표준화 vs 정규화

1. 표준화 (Standardization)

표준화는 값의 평균이 '0' 이고 분산이 '1' 인 정규분포를 가진 값으로 변환하는 작업을 의미하며, 다른 다뉘를 가진 피처(값, 컬럼)들에 대해 공통 기준으로 비교하기 위해 사용한다. 표준화는 원본데이터 분포의 모양을 바꿔주지 않고 그대로 유지하기 때문에 이상치 처리와의 순서는 무관하다.

 

2. 정규화 (Normalization)

정규화는 값을 0부터 1까지의 범위로 피처(값, 컬럼)를 재조정하는 작업을 의미하며, 데이터셋의 연속형변수 컬럼들에 대한 차이를 유지한 상태로 공통 척도로 변환할 때 사용한다. 정규화는 데이터에 최소값을 빼고 전체 범위로 나누는 과정을 거치기 때문에 이상치가 있으면 범위가 이상해질 수 있다. 따라서 이상치 처리 후 정규화를 진행하는 것이 좋다.

Ⅱ. SQL 코드카타

그동안은 with 구문을 활용을 잘 못해서 거의 쓴 적이 대부분 join이나 having 절로 해결했었는데, 이번에 with 구문을 처음 사용해 보았다.

 

코드카타 1)

문제에서는 고객 정보를 담은 MEMBER_PROFILE 테이블과 식당의 리뷰 정보를 담은 REST_REVIEW 테이블을 제공해주고, 두 테이블에서 리뷰를 가장 많이 작성한 회원의 리뷰들을 조회하는 SQL문을 작성해 달라고 했다. 처음엔 with 구문을 사용하지 않고, 최대한 한번에 쿼리를 작성해 보고자 했다. 하지만 서브쿼리는 피할 수 없었ㄷr.. 그렇게 짠 첫 쿼리는 아래와 같다:

select b.member_name, a.review_text, date_format(a.review_date, '%Y-%m-%d') as review_date
from rest_review as a
left join member_profile as b
on a.member_id = b.member_id
where a.member_id in (select member_id
	    	      from rest_review
                      group by member_id
                      having max(count(member_id)) )
order by review_date, a.review_text
;

 

그런데 having 절에서 오류가 났다. 집계함수는 한 번에 한 개 이상 사용할 수 없는 것 같았다. 나는 count 함수도 써야하고, max 함수도 써야하는 상황이라 멘붕이 왔다. 그래서 데이터를 살펴보고 max(count(member_id))에 해당하는 숫자를 직접 구해 쿼리를 짜보기로 했다.

select member_id, count(*)
from rest_review
group by member_id
order by count(*) desc
;

select b.member_name, a.review_text, date_format(a.review_date, '%Y-%m-%d') as review_date
from rest_review as a
left join member_profile as b
on a.member_id = b.member_id
where a.member_id in (	select member_id
			from rest_review
                        group by member_id
                        having count(member_id) >= 3 )
order by review_date, a.review_text
;

 

이 쿼리도 틀렸다고 나와서 참고한 정답쿼리 결과와 내 결과를 비교해보니 결과는 같았다. 다만, max 함수를 사용해야 정답 처리가 되는 것 같아 정답 쿼리를 참고해 with 구문을 사용해 보기로 했다.

with review_cnt as (
    select member_id, count(*) as rvw_cnt
    from rest_review
    group by member_id
)
select b.member_name, a.review_text, date_format(a.review_date, '%Y-%m-%d') as review_date
from rest_review as a
left join member_profile as b
on a.member_id = b.member_id
where a.member_id in ( select member_id
                       from rest_review
                       group by member_id
                       having count(member_id) >= (select max(rvw_cnt)
                                                   from review_cnt) )
order by review_date, a.review_text
;

 

with 구문을 사용하고서야 max 함수도 온전히 사용할 수 있게 되었고, 정답처리가 되었다. 원하는 결과를 얻기 위해 어떤 함수를 써야하는지는 알고 있지만, 구현하는데 아직 미숙한 것 같다. 코드카타 문제 레벨이 올라가면서 하루에 많이 풀지 못하지만 한 문제씩이라도 꾸준히 풀며 사고과정을 정리해 보는 연습을 하다보면 SQL적 사고(?)에 익숙해질 수 있지 않을까 한다.