DB 스터디 2주차

권재현·2021년 6월 6일
0

DB스터디

목록 보기
2/4

2주차 문제 시작
4문제
테이블은 1주차와 동일 OT

문제 1

주문 상태가 Pending이고, 주소에 1과 S가 들어가는 고객중 주문날짜가 가장 오래된 고객을 찾고,
그 고객의 풀네임의 길이와, 전체 고객중 풀네임의 길이가 일치하고, 주문이 완료된 고객의 주문번호와 고객의 이름, 폰번호, 주문상태, 주문날짜를 출력하시오.
추가로, 주문날짜가 오래된 순서로 정렬하시오.

주문 상태가 Pending이고, 주소에 1과 S가 들어가는 고객중 주문날짜가 가장 오래된 고객, 고객 풀네임길이

SELECT O.*,CU.ADDRESS,LENGTH(CO.FIRST_NAME || CO.LAST_NAME) AS FULLNAME,RANK() OVER( ORDER BY O.ORDER_DATE ASC) ROD
FROM ORDERS O INNER JOIN CUSTOMERS CU
                      ON O.CUSTOMER_ID = CU.CUSTOMER_ID
              INNER JOIN CONTACTS CO
                      ON CU.CUSTOMER_ID = CO.CUSTOMER_ID
                      AND O.STATUS = 'Pending' 
                      AND CU.ADDRESS LIKE '%1%S%'    
;

주문상태,주소 그리고 고객의 정보가 필요하기 때문에 ORDERS , CUSTOMERS, CONTACTS 테이블을 갖고온다. 그리고 AND 조건으로 Pending 과 주소 1과 S를 위해 like로 테이블을 가공한다. SELETE에서 LENGTH 함수를 통해서 풀네임 길이까지 구하고 랭크를 통해 주문날짜별 순위도 출력했다.
출력

정답

전체 고객중 풀네임의 길이가 일치하고, 주문이 완료된 고객의 주문번호와 고객의 이름, 폰번호, 주문상태, 주문날짜를 출력하시오.
추가로, 주문날짜가 오래된 순서로 정렬하시오.

SELECT O.ORDER_ID,C.FIRST_NAME,C.PHONE,O.STATUS,O.ORDER_DATE
FROM CONTACTS C INNER JOIN ORDERS O
                        ON C.CUSTOMER_ID = O.CUSTOMER_ID
                       AND O.STATUS = 'Shipped'
                INNER JOIN (SELECT *
                            FROM (  SELECT O.*,CU.ADDRESS,LENGTH(CO.FIRST_NAME || CO.LAST_NAME) AS FULLNAME,RANK() OVER( ORDER BY O.ORDER_DATE ASC) ROD
                                    FROM ORDERS O INNER JOIN CUSTOMERS CU
                                                          ON O.CUSTOMER_ID = CU.CUSTOMER_ID
                                                  INNER JOIN CONTACTS CO
                                                          ON CU.CUSTOMER_ID = CO.CUSTOMER_ID
                                                          AND O.STATUS = 'Pending' 
                                                          AND CU.ADDRESS LIKE '%1%S%' ) P
                            WHERE P.ROD = 1) P2
                       ON 1=1
                      AND LENGTH(C.FIRST_NAME || C.LAST_NAME) = P2.FULLNAME
ORDER BY O.ORDER_DATE ASC                        
;

출력조건을 위해서 CONTACTS 테이블과 주문완료조건을 위해 ORDERS 테이블 조인한 후 AND 조건으로 STATUS 를 Shipped 를 넣는다. 그다음 위에서 만든 테이블(1등만 뽑은 테이블)을 조인 시켜서 1=1로 붙이고 AND 조건에 LENGTH 로 풀네임 길이 같은 사람만 나온다.

마지막으로 ORDER BY 로 출력순서를 오름차순 정렬한다.

문제2

현재 판매가 기준으로 가장 많은 매출을 낸 사원의 이름을 출력하고 매출액의 200%만큼 보너스를 부여하시오
출력필드 [FIRST_NAME,보너스]

판매가 기준 많은 매출을 낸 사원 번호

SELECT O.SALESMAN_ID,SUM(OI.QUANTITY * OI.UNIT_PRICE),
        RANK() OVER(ORDER BY  SUM(OI.QUANTITY * OI.UNIT_PRICE)DESC) AS RNK 
FROM ORDER_ITEMS OI RIGHT OUTER JOIN ORDERS O
                            ON OI.ORDER_ID = O.ORDER_ID
WHERE O.SALESMAN_ID IS NOT NULL
GROUP BY O.SALESMAN_ID
;

판매가 기준이기 때문에 ORDER_ITEMS 테이블에서 수량과 현재가인 UNIT_PRICE가 필요하다. 또 사원정보가 필요해 ORDERS에 사원번호가 있어 둘이 조인 시켰다. 마지막으로 GROUP BY에 SALESMAN_ID 을 넣고 그룹화시킨 결과 매출 1등의 사원번호가 NULL 이나와서 WHERE IN NOT NULL을 추가해서 다시출력했다.

출력

정답

SELECT E.FIRST_NAME,S.SALES,(S.SALES*2) AS BONUS
FROM EMPLOYEES E INNER JOIN (SELECT O.SALESMAN_ID,SUM(OI.QUANTITY * OI.UNIT_PRICE) AS SALES,
                                    RANK() OVER(ORDER BY  SUM(OI.QUANTITY * OI.UNIT_PRICE)DESC) AS RNK 
                             FROM ORDER_ITEMS OI RIGHT OUTER JOIN ORDERS O
                                                        ON OI.ORDER_ID = O.ORDER_ID
                             WHERE O.SALESMAN_ID IS NOT NULL
                             GROUP BY O.SALESMAN_ID) S
                        ON E.EMPLOYEE_ID = S.SALESMAN_ID
                       AND S.RNK = 1                
;

사원정보가 필요해 EMPLOYEES 테이블과 서브쿼리 테이블을 조인 시키고 문제의 마지막 조건인 매출의 200% 가 보너스이기에 SALES * 2를 해서 별칭 보너스를 붙여서 출력했다.
출력

문제 3

신용한도가 600이상인 회사중 가장 많은 주문을 한 회사를 찾고 해당 회사들 중 이름이 6글자 이상인 담당자를 찾으시오.(LAST_NAME기준)
출력 : FULL NAME, WITHOUT DOMAIN, KOREA NUMBER(단, 답과 똑같이 출력하시오)

신용한도가 600이상인 회사중 가장 많은 주문을 한 회사

SELECT *
FROM (SELECT C.CUSTOMER_ID,COUNT(*),
               RANK() OVER (ORDER BY COUNT(*) DESC) AS RNK
      FROM CUSTOMERS C INNER JOIN ORDERS O
                                 ON C.CUSTOMER_ID =O.CUSTOMER_ID
                                AND C.CREDIT_LIMIT >= 600
      GROUP BY C.CUSTOMER_ID ) C
WHERE C.RNK = 1
;

CUSTOMERS 테이블에 신용한도가 있고, 주문정보가 필요해 ORDERS 테이블 서로 조인 시켰고 신용한도 600이상 조건으로 AND 에 넣었고, GROUP BY 을 CUSTOMER_ID 해서 주문 개수를 COUNT해서 구했다. COUNT 기준으로 순위를 구했다.

정답

SELECT CO.FIRST_NAME || CO.LAST_NAME AS FULLNAME,SUBSTR(CO.EMAIL,0,INSTR(CO.EMAIL,'@')-1) AS WITHOUT_DOMAIN,CO.PHONE,REPLACE(CO.PHONE,'+1','+82') AS KOREA_NUMBER
FROM CONTACTS CO INNER JOIN (SELECT *
                             FROM (SELECT C.CUSTOMER_ID,COUNT(*),
                                           RANK() OVER (ORDER BY COUNT(*) DESC) AS RNK
                                   FROM CUSTOMERS C INNER JOIN ORDERS O
                                                             ON C.CUSTOMER_ID =O.CUSTOMER_ID
                                                            AND C.CREDIT_LIMIT >= 600
                                  GROUP BY C.CUSTOMER_ID ) C
                            WHERE C.RNK = 1) C2
                          ON CO.CUSTOMER_ID = C2.CUSTOMER_ID
                         AND LENGTH(CO.LAST_NAME) >= 6             
;

담당자의 이름이 필요하기에 CONTACTS 테이블을 조인시켰고, 풀네임 6글자 이상 AND조건에서 LENGTH로 처리했다. 그다음 출력조건에 필요한 함수 SUBSTR,INSTR,REPLACE 을 통해 구했다.
출력

문제4(건정)
ASUS사 CPU종류의 주문수량을 오름차순하시오.
출력 : 오름차순, PRODUCT_NAME, DESCRIPTION

이번 문제는 테이블 파악할 수 있으면 충분히 풀 수 있고, like 사용하면 끝난다.
그래서 다른 추가 설명은 괜찮을 것 같다.
출력
56줄까지 있다.

2주차도 무사히 마쳤고, 1주차 문제들보다는 상대적으로 난이도가 쉬워서 금방 끝났다.
다음주에 확실히 조금 더 난이도 올려서 내봐야겠다는 생각을 한다.
7월부터는 진짜로 샘한테 부탁해서 3문제정도만 풀 수 있게 부탁드려야 봐야겠다.

profile
호텔리어 출신 비전공자

0개의 댓글