인프런 커뮤니티 질문&답변

Dash Choi님의 프로필 이미지
Dash Choi

작성한 질문수

다양한 사례로 익히는 SQL 데이터 분석

주문별 고객별 연관 상품 추출 SQL로 구하기 - 02

고객별 연관 상품 추출 수업 관련 질문

작성

·

366

1

안녕하세요,

주변별 고객별 연관 상품 추출 sql 구하기 -02

수업 관련해서 질문 드리겠습니다.

해당 쿼리문 결과값 중 'cnt' 열에 해당되는 횟수가 출력이 되는데, 예를 들면 위 사진에 보이는 출력 열 'cnt' 3에 해당되는 user_id 를 알고 싶을 때는 어떤 쿼리를 작성해야되나요?

 

답변 1

1

권 철민님의 프로필 이미지
권 철민
지식공유자

안녕하십니까,

명절 관계로 답변이 좀 늦었습니다.

cnt에 해당하는 user_id가 정확히 어떤 의미인지를 잘 모르겠군요.

group by 를 prod_01, prod_02로 하였기 때문에 cnt는 temp_01 집합의 prod_01 + prod_02의 건수입니다.

다만 추측컨데 temp_01 집합에 대해서 prod_01 + prod_02 레벨에 해당하는 user_id 정보를 추출하고자 하는걸로 가정해서 말씀드리겠습니다.

먼저 아래 temp_02 집합에서 group by가 prod_01 + prod_02로 집합 레벨(유일 집합)이 변경되었으므로 user_id는 ANSI-SQL 상으로는 추출할 수가 없습니다.

temp_02 as (

select prod_01, prod_02, array_to_string(array_agg(user_id), ',') customer_array, count(*) as cnt

from temp_01

group by prod_01, prod_02

)

다만 유일한 prod_01 + prod_02 에 해당하는 user_id 하나를 대표 user_id로 max(user_id)와 같이 추출하는 방법이 있을수 있고,

다음으로는 특정 집합에 group by 를 적용하기 전 집합 레벨로 특정 컬럼들을 array 형태로 추출하는 함수를 DBMS 별로 제공하고 있습니다. PostgreSQL은 array_agg()함수를 사용하는데 보통은 이 array를 string으로 변환하는 array_to_string()과 함께 사용합니다.

그래서 temp_02를 생성할 때 아래와 같이 array_to_stirng(array_agg(user_id), delimeter 문자열)을 사용하게 되면 prod_0a + prod_02 레벨에 해당하는 user_id를 배열 형태의 문자열로 반환하게 됩니다.

temp_02 as (

select prod_01, prod_02, array_to_string(array_agg(user_id), ',') as user_id_array, count(*) as cnt

from temp_01

group by prod_01, prod_02

)

아래는 전체 SQL이니 참조하시기 바랍니다.

with

-- user_id는 order_items에 없으므로 order_items와 orders를 조인하여 user_id 추출.

temp_00 as (

select b.user_id,a.order_id, a.product_id

from order_items a

join orders b on a.order_id = b.order_id

),

-- temp_00을 user_id로 셀프 조인하면 M:M 조인되면서 개별 user_id별 주문 상품별로 연관된 주문 상품 집합을 생성

temp_01 as

(

select a.user_id, a.product_id as prod_01, b.product_id as prod_02

from temp_00 a

join temp_00 b on a.user_id = b.user_id

where a.product_id != b.product_id

),

-- prod_01 + prod_02 레벨로 group by 건수를 추출.

temp_02 as (

select prod_01, prod_02, array_to_string(array_agg(user_id), ',') as user_id_array, count(*) as cnt

from temp_01

group by prod_01, prod_02

),

temp_03 as (

select prod_01, prod_02, user_id_array, cnt

-- prod_01별로 가장 많은 건수를 가지는 prod_02를 찾기 위해 cnt가 높은 순으로 순위추출.

, row_number() over (partition by prod_01 order by cnt desc) as rnum

from temp_02

)

-- 순위가 1인 데이터만 별도 추출.

select prod_01, prod_02, user_id_array, cnt, rnum

from temp_03

where rnum = 1

;

 

감사합니다.

Dash Choi님의 프로필 이미지
Dash Choi

작성한 질문수

질문하기