ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SQL 4. SQL 활용_데이터 마트
    SYNC 기술면접 준비 2023. 11. 14. 17:17

    <데이터 마트>

    분석에 필요한 데이터를 가공한 분석용 데이터

     

    요약변수 : 수집된 데이터를 분석에 맞게 종합한 변수(기간별 구매 금액, 횟수, 수량 등)

    파생변수 : 사용자가 특정 조건 또는 함수로 의미를 부여한 변수(연령대, 선호 카테고리 등)

     

    USE PRACTICE;
    /*****************************회원 분석용 데이터 마트******************************/
    /***************회원 구매정보***************/
    /* 회원 구매정보 */

    SELECT A.MEM_NO, A.GENDER, A.BIRTHDAY, A.ADDR, A.JOIN_DATE,
    SUM(B.SALES_QTY * C.PRICE) AS 구매금액,
    COUNT(B.ORDER_NO) AS 구매횟수,
    SUM(B.SALES_QTY) AS 구매수량
    FROM CUSTOMER AS A
    LEFT JOIN SALES AS B
    ON A.MEM_NO = B.MEM_NO
    LEFT JOIN PRODUCT AS C
    ON B.PRODUCT_CODE = C.PRODUCT_CODE
    GROUP BY A.MEM_NO, A.GENDER, A.BIRTHDAY, A.ADDR, A.JOIN_DATE;

    /* 회원 구매정보 임시테이블 */
    CREATE TEMPORARY TABLE CUSTOMER_PUR_INFO AS
    SELECT A.MEM_NO, A.GENDER, A.BIRTHDAY, A.ADDR, A.JOIN_DATE,
    SUM(B.SALES_QTY * C.PRICE) AS 구매금액,
    COUNT(B.ORDER_NO) AS 구매횟수,
    SUM(B.SALES_QTY) AS 구매수량
    FROM CUSTOMER AS A
    LEFT JOIN SALES AS B
    ON A.MEM_NO = B.MEM_NO
    LEFT JOIN PRODUCT AS C
    ON B.PRODUCT_CODE = C.PRODUCT_CODE
    GROUP BY A.MEM_NO, A.GENDER, A.BIRTHDAY, A.ADDR, A.JOIN_DATE;

    /***************회원 연령대***************/
    /* 생년월일 -> 나이 */
    SELECT *, 2023-YEAR(BIRTHDAY)+1 AS 나이
    FROM CUSTOMER;

    /* 생년월일 -> 나이 -> 연령대 */
    SELECT * , CASE WHEN 나이 < 20 THEN '청소년'
    WHEN 나이 < 60 THEN '청장년'
                    WHEN 나이 < 80 THEN '노년'
    ELSE '건강주의' END AS 연령층
    FROM (
    SELECT *, 2023-YEAR(BIRTHDAY)+1 AS 나이
    FROM CUSTOMER
            ) AS A;
            
    /* CASE WHEN 함수 사용시 주의점(순차적) */ /* 10, 20, 30 대가 반환되지 않는다. */
    SELECT  *
    ,CASE WHEN 나이 < 50 THEN '40대'
      WHEN 나이 < 10 THEN '10대 미만'
                  WHEN 나이 < 20 THEN '10대'
                  WHEN 나이 < 30 THEN '20대'
                  WHEN 나이 < 40 THEN '30대'
                  ELSE '50대 이상' END AS 연령층        
      FROM  (
    SELECT  *
    ,2021-YEAR(BIRTHDAY) +1 AS 나이
      FROM  CUSTOMER
    )AS A; 
            
    /* 회원 연령대 임시테이블 */
    CREATE TEMPORARY TABLE CUSTOMER_AGEBAND AS
    SELECT * , CASE WHEN 나이 < 20 THEN '청소년'
    WHEN 나이 < 60 THEN '청장년'
                    WHEN 나이 < 80 THEN '노년'
    ELSE '건강주의' END AS 연령층
    FROM (
    SELECT *, 2023-YEAR(BIRTHDAY)+1 AS 나이
    FROM CUSTOMER
            ) AS A;
            
    /* 확인 */
    SELECT * FROM CUSTOMER_AGEBAND;

    /***************회원 구매정보 + 연령대 임시테이블***************/
    CREATE TEMPORARY TABLE CUSTOMER_PUR_INFO_AGEBAND AS
    SELECT A.*, B.연령층
    FROM  CUSTOMER_PUR_INFO AS A
    LEFT JOIN CUSTOMER_AGEBAND AS B
    ON  A.MEM_NO = B.MEM_NO;

    /* 확인 */
    SELECT * FROM CUSTOMER_PUR_INFO_AGEBAND;

    /***************회원 선호 카테고리***************/
    /* 회원 및 카테고리별 구매횟수 순위 */
    SELECT  A.MEM_NO, B.CATEGORY, COUNT(A.ORDER_NO) AS 구매횟수,
    ROW_NUMBER() OVER(PARTITION BY A.MEM_NO ORDER BY COUNT(A.ORDER_NO) DESC) AS 구매횟수_순위
    FROM  SALES AS A
    LEFT JOIN  PRODUCT AS B
    ON  A.PRODUCT_CODE = B.PRODUCT_CODE   
    GROUP BY  A.MEM_NO, B.CATEGORY;

    /* ROW_NUMBER : 같은 값이어도 고유한 순위를 반환한다. */

    /* 회원 및 카테고리별 구매횟수 순위 + 구매횟수 순위 1위만 필터링 */
    SELECT * 
    FROM( SELECT  A.MEM_NO, B.CATEGORY, COUNT(A.ORDER_NO) AS 구매횟수,
    ROW_NUMBER() OVER(PARTITION BY A.MEM_NO ORDER BY COUNT(A.ORDER_NO) DESC) AS 구매횟수_순위
    FROM  SALES AS A
    LEFT JOIN  PRODUCT AS B
    ON  A.PRODUCT_CODE = B.PRODUCT_CODE   
    GROUP BY  A.MEM_NO, B.CATEGORY) AS A
    WHERE 구매횟수_순위 = 1;
    /*ROW NUMBER 사용해서 고유한 순위를 주었기 때문에 중복되는 회원은 없다.*/

    /* 회원 선호 카테고리 임시테이블 */
    CREATE TEMPORARY TABLE CUSTOMER_PRE_CATEGORY AS
    SELECT * 
    FROM( SELECT  A.MEM_NO, B.CATEGORY, COUNT(A.ORDER_NO) AS 구매횟수,
    ROW_NUMBER() OVER(PARTITION BY A.MEM_NO ORDER BY COUNT(A.ORDER_NO) DESC) AS 구매횟수_순위
    FROM  SALES AS A
    LEFT JOIN  PRODUCT AS B
    ON  A.PRODUCT_CODE = B.PRODUCT_CODE   
    GROUP BY  A.MEM_NO, B.CATEGORY) AS A
    WHERE 구매횟수_순위 = 1;

    /* 확인 */
    SELECT * FROM CUSTOMER_PRE_CATEGORY;

    /***************회원 구매정보 + 연령대 + 선호 카테고리 임시테이블***************/
    CREATE TEMPORARY TABLE CUSTOMER_PUR_INFO_AGEBRAND_PRE_CATEGORY AS 
    SELECT A.*, B.CATEGORY AS PRE_CATEGORY
    FROM CUSTOMER_PUR_INFO_AGEBAND AS A
    LEFT JOIN CUSTOMER_PRE_CATEGORY AS B
    ON A.MEM_NO = B.MEM_NO;

    /*확인*/
    SELECT  * FROM CUSTOMER_PUR_INFO_AGEBRAND_PRE_CATEGORY;

    /***************회원 분석용 데이터 마트 생성(회원 구매정보 + 연령대 + 선호 카테고리 임시테이블)***************/
    CREATE TABLE CUSTOMER_MART AS
    SELECT * 
    FROM CUSTOMER_PUR_INFO_AGEBRAND_PRE_CATEGORY;

    /* 확인 */    
    SELECT  *  FROM  CUSTOMER_MART;

     

     

    데이터 마트 - 데이터 적합성

    데이터 적합성은 데이터가 서로 모순 없이 일관되게 일치함을 나타낼 떄 사용된다.

    1. 데이터 마트의 회원수의 중복은 없는가?

    2. 데이터 마트의 요약 및 파생변수의 오류는 없는가?

    3. 데이터 마트의 구매자 비중(%)의 오류는 없는가?

     

     

     

    /***************회원 분석용 데이터 마트 생성(회원 구매정보 + 연령대 + 선호 카테고리 임시테이블)***************/
    CREATE TABLE CUSTOMER_MART AS
    SELECT * 
    FROM CUSTOMER_PUR_INFO_AGEBRAND_PRE_CATEGORY;

    /* 확인 */    
    SELECT  *  FROM  CUSTOMER_MART;

    /*********************************데이터 정합성**********************************/
    SELECT * FROM CUSTOMER_MART;
    /* DISTINCT : 중복없이 */ 
    SELECT COUNT(MEM_NO), COUNT(DISTINCT MEM_NO)
    FROM CUSTOMER_MART;

    /* 회원(1000005)의 구매정보 */
    /* 구매금액: 408000 / 구매횟수: 3 구매수량: 14 */
    SELECT MEM_NO, SUM(SALES_QTY*PRICE) AS 구매금액,
    COUNT(A.ORDER_NO) AS 구매횟수,
            SUM(SALES_QTY) AS 구매수량
    FROM SALES AS A
    LEFT JOIN PRODUCT AS B
    ON A.PRODUCT_CODE = B.PRODUCT_CODE
    WHERE MEM_NO = '1000005';

    /* 회원(1000005)의 선호 카테고리 */
    SELECT * 
    FROM SALES A
    LEFT JOIN CUSTOMER_PRE_CATEGORY AS B
    ON A.PRODUCT_CODE = B.PRODUCT_CODE
    WHERE MEM_NO = '1000005';


    /***************데이터 마트의 구매자 비중(%)의 오류는 없는가?***************/
    /* 회원(Customer) 테이블 기준, 주문(Sales) 테이블 구매 회원번호 LEFT JOIN 결합 */
    SELECT * 
    FROM CUSTOMER AS A
    LEFT JOIN(
    SELECT distinct MEM_NO
        FROM SALES) AS B
    ON A.MEM_NO = B.MEM_NO;

    /* 회원(Customer) 테이블 기준, 주문(Sales) 테이블 구매 회원번호 LEFT JOIN 결합 */
    /* 구매여부 추가 */
    SELECT * ,
    CASE WHEN B.MEM_NO IS NOT NULL then '구매'
    ELSE '비구매' END AS 구매여부
    FROM CUSTOMER AS A
    LEFT JOIN(
    SELECT distinct MEM_NO
        FROM SALES) AS B
    ON A.MEM_NO = B.MEM_NO;

    /* 구매여부별, 회원수 */
    SELECT  구매여부, COUNT(MEM_NO) AS 회원수
      FROM  (
    SELECT  A.*, CASE WHEN B.MEM_NO IS NOT NULL THEN '구매'
      ELSE '미구매' END AS 구매여부
      FROM  CUSTOMER AS A
      LEFT JOIN  (
    SELECT  DISTINCT MEM_NO
    FROM  SALES
    )AS B
      ON  A.MEM_NO = B.MEM_NO
    )AS A
     GROUP BY  구매여부; 
     
    /* 확인 */
    /* 확인(미구매: 1459 / 구매: 1202) */ 
    SELECT  *
    FROM  CUSTOMER_MART
     WHERE  구매금액 IS NULL; /*미구매*/
     
    SELECT  *
    FROM  CUSTOMER_MART
     WHERE  구매금액 IS NOT NULL; /*구매*/

    'SYNC 기술면접 준비' 카테고리의 다른 글

    SQL 4. SQL 활용_연산자 및 함수(2)  (1) 2023.11.14
    SQL 4. SQL 활용_연산자 및 함수(1)  (1) 2023.11.13
    SQL 3. SQL 문법_총정리  (0) 2023.11.13
    SQL 3. SQL 문법_SUB QUERY  (1) 2023.11.13
    SQL 3. SQL 문법_JOIN  (0) 2023.11.13
Designed by Tistory.