공부한것들을 정리하는 블로그 입니다.
(작성중) Oracle : 협업 필터링(collaborative filtering) SQL로 작성 본문
--샘플 데이타 입력
CREATE TABLE TBL_ORDER (
ORDERSERIAL VARCHAR2(32) NOT NULL, --결제번호
USERID VARCHAR2(32) NOT NULL, --구매자ID
ITEMID NUMBER(11) NOT NULL, --상품번호
PRIMARY KEY (ORDERSERIAL,USERID,ITEMID)
)
;
INSERT ALL
INTO TBL_ORDER VALUES ('20190701000000001', 'A', 1)
INTO TBL_ORDER VALUES ('20190701000000001', 'A', 2)
INTO TBL_ORDER VALUES ('20190701000000001', 'A', 3)
INTO TBL_ORDER VALUES ('20190701000000002', 'B', 1)
INTO TBL_ORDER VALUES ('20190701000000002', 'B', 4)
INTO TBL_ORDER VALUES ('20190701000000003', 'C', 2)
INTO TBL_ORDER VALUES ('20190701000000003', 'C', 3)
INTO TBL_ORDER VALUES ('20190701000000003', 'C', 5)
INTO TBL_ORDER VALUES ('20190701000000004', 'D', 1)
INTO TBL_ORDER VALUES ('20190701000000004', 'D', 2)
INTO TBL_ORDER VALUES ('20190701000000004', 'D', 6)
SELECT *
FROM DUAL
;
INSERT ALL
INTO TBL_ORDER VALUES ('20190701000000005', 'A', 1)
INTO TBL_ORDER VALUES ('20190701000000005', 'A', 2)
INTO TBL_ORDER VALUES ('20190701000000005', 'A', 6)
SELECT *
FROM DUAL
;
COMMIT;
--확인
SELECT * FROM
TBL_ORDER;
--협업 필터링(collaborative filtering) SQL을 이용하여 기능
--해석)TEMP를 구매하였으면서 TEMP2를 구매한 고객의 수 = CNT
SELECT A.ITEMID AS TEMP, B.ITEMID AS TEMP2, COUNT(B.ITEMID) AS CNT
FROM
TBL_ORDER A
JOIN TBL_ORDER B
ON
1 = 1
AND A.ORDERSERIAL = B.ORDERSERIAL
AND A.USERID = B.USERID
AND A.ITEMID <> B.ITEMID
GROUP BY
A.ITEMID, B.ITEMID
ORDER BY
A.ITEMID, B.ITEMID, COUNT(B.ITEMID) DESC;
--웹로그 정제
CREATE TABLE TBL_WEBLOG (
YYYYMMDDHHMMSS VARCHAR2(32) NOT NULL,
USERID VARCHAR2(32) NOT NULL,
ITEMID NUMBER(11) NOT NULL,
PRIMARY KEY (YYYYMMDDHHMMSS,USERID,ITEMID)
);
INSERT ALL
INTO TBL_WEBLOG VALUES ('2019-07-01 11:22:33', 'A', 1)
INTO TBL_WEBLOG VALUES ('2019-07-01 12:22:33', 'A', 2)
INTO TBL_WEBLOG VALUES ('2019-07-01 13:22:33', 'A', 3)
INTO TBL_WEBLOG VALUES ('2019-07-01 11:40:33', 'B', 1)
INTO TBL_WEBLOG VALUES ('2019-07-01 11:41:33', 'B', 4)
INTO TBL_WEBLOG VALUES ('2019-07-01 09:22:33', 'C', 2)
INTO TBL_WEBLOG VALUES ('2019-07-01 09:55:33', 'C', 3)
INTO TBL_WEBLOG VALUES ('2019-07-01 09:59:33', 'C', 5)
INTO TBL_WEBLOG VALUES ('2019-07-01 15:22:33', 'D', 1)
INTO TBL_WEBLOG VALUES ('2019-07-01 16:22:33', 'D', 2)
INTO TBL_WEBLOG VALUES ('2019-07-01 17:22:33', 'D', 6)
SELECT *
FROM DUAL
;
INSERT ALL
INTO TBL_WEBLOG VALUES ('2019-07-02 15:22:33', 'A', 1)
INTO TBL_WEBLOG VALUES ('2019-07-02 16:22:33', 'A', 2)
INTO TBL_WEBLOG VALUES ('2019-07-02 17:22:33', 'A', 6)
SELECT *
FROM DUAL
;
COMMIT;
--같은 날짜에 본 상품을 같이 본 상품으로 정하면 동일한 쿼리를 적용할 수 있습니다.
SELECT A.ITEMID AS TEMP, B.ITEMID AS TEMP2, COUNT(B.ITEMID) AS CNT
FROM
TBL_WEBLOG A
JOIN TBL_WEBLOG B
ON
1 = 1
AND LPAD(A.YYYYMMDDHHMMSS, 10) = LPAD(B.YYYYMMDDHHMMSS, 10)
AND A.USERID = B.USERID
AND A.ITEMID <> B.ITEMID
GROUP BY
A.ITEMID, B.ITEMID
ORDER BY
A.ITEMID, B.ITEMID, COUNT(B.ITEMID) DESC;
--여기까지는 협업 필터링을 SQL 로 구현한 것에 불과하고 실제로 서비스에는 사용할 수 없는 데이타입니다.
--같이 구매한 상품 을 예로 들어봅니다. 우리가 원하는 같이 구매한 상품은 "노트북을 살 때 마우스도 같이 살 것이다" 라는 생각이지만 현실은 베스트셀러가 같이 구매한 상품이 되는 경우가 더 많습니다.
--간단한 예로 엑셀 도서를 구매하려는 고객이 있습니다. 그런데 메인 페이지에 삼겹살이 특가로 세일을 하여 그것을 본 고객은 엑셀도서와 삼겹살을 같이 구매하게 되는거죠.
--위 문제를 해결하는 가장 간단한 방법은 카테고리 제한이었습니다.
CREATE TABLE tbl_order_v2 (
orderserial varchar2(32) NOT NULL,
userid varchar2(32) NOT NULL,
category varchar2(32) NOT NULL,
itemid number(11) NOT NULL,
PRIMARY KEY (orderserial,userid,itemid)
);
insert all
into tbl_order_v2 values ('20190701000000001', 'A', 'book', 1)
into tbl_order_v2 values ('20190701000000001', 'A', 'book', 2)
into tbl_order_v2 values ('20190701000000001', 'A', 'food', 3)
into tbl_order_v2 values ('20190701000000002', 'B', 'book', 1)
into tbl_order_v2 values ('20190701000000002', 'B', 'food', 4)
into tbl_order_v2 values ('20190701000000003', 'C', 'book', 2)
into tbl_order_v2 values ('20190701000000003', 'C', 'food', 3)
into tbl_order_v2 values ('20190701000000003', 'C', 'food', 5)
into tbl_order_v2 values ('20190701000000004', 'D', 'book', 1)
into tbl_order_v2 values ('20190701000000004', 'D', 'book', 2)
into tbl_order_v2 values ('20190701000000004', 'D', 'food', 6)
select *
from dual
;
commit;
--협업조회
select A.itemid, B.itemid, count(B.itemid) as cnt
from
tbl_order_v2 A
join tbl_order_v2 B
on
1 = 1
and A.orderserial = B.orderserial
and A.userid = B.userid
and A.category = B.category
and A.itemid <> B.itemid
group by
A.itemid, B.itemid
order by
A.itemid, count(B.itemid) desc;
참고 :
https://github.com/skyer9/collaborative-filtering-in-mysql
'DB 공부' 카테고리의 다른 글
oracle execution plan 실행계획 순서 (0) | 2020.06.11 |
---|---|
오라클 힌트(oracle hint) : FIRST_ROWS vs. FIRST_ROWS_N 그리고 Cost의 개념 (0) | 2020.05.15 |
오라클 실행계획 보는법 (0) | 2019.12.17 |
ORACLE과 MYSQL의 차이점 비교 (0) | 2019.11.29 |
Oracle : 다건 insert (0) | 2019.07.10 |
Oracle : 계층형 쿼리 (0) | 2019.06.28 |
오라클 컬럼명으로 테이블 찾기 (0) | 2019.06.25 |
SQL컬럼으로 sql삽입 (0) | 2019.06.11 |