문제 1 : 첫 주문 고객 연도별 매출 조회


“2011년 12월”에 첫 주문을 한 고객들의 연도별 매출을 조회하는 SQL 문을 작성하세요. 고객 이름은 이름과 성을 결합하여 생성합니다. 결과는 고객 ID(customerid)기준 오름차순, 연도(year) 기준 오름차순으로 정렬합니다.'

 

[풀이]

1. 11년 12월에 첫 주문한 고객을 필터링해야 하므로 sales_order 테이블에서 고객별로 그룹화 한 뒤 MIN 함수를 통해 첫 주문을 계산하고, 계산한 값이 11년 12월인 고객만 필터링한다.

SELECT cutomerid
FROM sales_order
GROUP BY customerid
HAVING MIN(orderdate) LIKE '2011-12%'

11년 12월에 첫 주문을 한 고객들

 

2. 위 쿼리를 서브쿼리로 WHERE 절로 보내, 11년 12월 첫주문한 고객들을 customer 테이블에서 필터링해주고,

customerid 와 firstname과 lastname을 이어붙인 customer_name을 출력해준다.

SELECT 
    customerid
    , CONCAT_WS(' ', firstname, lastname) AS customer_name
FROM customer
WHERE customerid in (SELECT customerid
                     FROM sales_order
                     GROUP BY customerid
                     HAVING MIN(orderdate) LIKE '2011-12%')

 

 

위 테이블에 속해있는 고객들의 연도별 매출을 구해야하므로, sales_order 테이블과 customerid를 기준으로 JOIN한다.

그 후 고객과 연도별로 그룹화 한뒤(GROUP BY customerid, year), 매출(unitprice * orderqty의 합계)을 구해준다. 정렬 기준에 맞게 정렬해주면 끝.

 

SELECT
    sub.customerid
    , sub.customer_name
    , YEAR(s.orderdate) AS year
    , SUM(s.unitprice * s.orderqty) AS gmv
FROM sales_order s
JOIN
(
    SELECT
        customerid
        , CONCAT_WS(' ', firstname, lastname) AS customer_name
    FROM customer
    WHERE customerid IN (SELECT customerid
                         FROM sales_order
                         GROUP BY customerid
                         HAVING MIN(orderdate) LIKE '2011-12%')
) sub
ON s.customerid = sub.customerid
GROUP BY customerid, year
ORDER BY customerid, year

 

 

 

문제 2 : 고객별 연평균 총 거래액 집계


2011년 12월에 첫 주문을 한 각 고객의 첫 주문과 마지막 주문 사이의 기간을 기준으로, 해당 기간 동안의 **연평균 총거래액(GMV)**을 계산합니다. 소수점 2째자리까지 계산해주세요.

결과는 고객 ID(customerid) 기준으로 오름차순으로 정렬합니다.

 

[풀이]

1. 앞서 구한 테이블을 CTE 테이블로 보내주고, 해당 테이블에서 고객별로 마지막주문과 첫주문의 연도 차이를 계산한 후 1을 더해 고객별로 기간을 나타내는 테이블을 하나 더 만들어준다.

WITH t1 AS (
    SELECT
        sub.customerid
        , sub.customer_name
        , YEAR(s.orderdate) AS year
        , SUM(s.unitprice * s.orderqty) AS gmv
    FROM sales_order s
    JOIN
    (
        SELECT
            customerid
            , CONCAT_WS(' ', firstname, lastname) AS customer_name
        FROM customer
        WHERE customerid IN (SELECT customerid
                             FROM sales_order
                             GROUP BY customerid
                             HAVING MIN(orderdate) LIKE '2011-12%')
    ) sub
    ON s.customerid = sub.customerid
    GROUP BY customerid, year
    ORDER BY customerid, year
)
SELECT
    customerid
    , MAX(year)-MIN(year)+1 AS period
FROM t1
GROUP BY customerid

 

 

2. 만들어진 테이블도 CTE로 보내버리고, 앞서 만든 테이블과 customerid를 키로 JOIN해준 뒤 고객별로 그룹화하여 gmv의 합계를 period으로 나누어준다. 그런다음 정렬기준에 맞게 정렬하면 끝

WITH t1 AS (
    SELECT
        sub.customerid
        , sub.customer_name
        , YEAR(s.orderdate) AS year
        , SUM(s.unitprice * s.orderqty) AS gmv
    FROM sales_order s
    JOIN
    (
        SELECT
            customerid
            , CONCAT_WS(' ', firstname, lastname) AS customer_name
        FROM customer
        WHERE customerid IN (SELECT customerid
                             FROM sales_order
                             GROUP BY customerid
                             HAVING MIN(orderdate) LIKE '2011-12%')
    ) sub
    ON s.customerid = sub.customerid
    GROUP BY customerid, year
    ORDER BY customerid, year
),
t2 AS (
    SELECT
        customerid
        , MAX(year)-MIN(year)+1 AS period
    FROM t1
    GROUP BY customerid
)
SELECT
    t1.customerid
    , t1.customer_name
    , ROUND(SUM(gmv)/period, 2) AS avg_yearly_gmv
FROM t1
JOIN t2
	ON t1.customerid = t2.customerid
GROUP BY customerid
ORDER BY customerid

 

 

문제 3 :고객별 최대 주문 수량 연도와 주문 수량 집계


2011년 12월에 첫 주문을 한 고객 대상으로, 고객별 각 연도에서의 주문 수량을 집계하고, 최대 주문 수량과 그 최대 주문 수량을 발생시킨 연도를 찾습니다.

최대 주문 수량이 같은 연도가 있다면, 가장 최근 연도를 출력합니다.

결과는 고객 ID(customerid) 기준으로 오름차순으로 정렬합니다.

 

[풀이]

1. 2011년 12월 첫주문 고객테이블과 sales_order 테이블을 병합해주고, 연도를 구해준 뒤, 고객과 연도별로 GROUP BY 해주고, orderqty를 SUM 해준다.

SELECT 
    sub.customerid
    , sub.customer_name
    , YEAR(s.orderdate) AS year
    , SUM(s.orderqty) AS total_orderqty
FROM sales_order s
JOIN
(
    SELECT
        customerid
        , CONCAT_WS(' ', firstname, lastname) AS customer_name
    FROM customer
    WHERE customerid IN (SELECT customerid
                         FROM sales_order
                         GROUP BY customerid
                         HAVING MIN(orderdate) LIKE '2011-12%')
) sub
ON s.customerid = sub.customerid
GROUP BY customerid, year
ORDER BY customerid, year

 

2. 위 테이블을 CTE로 보낸 뒤 해당 테이블에서 고객별로 파티션을 나눈 총주문수량을 내림차순으로 해서 순위를 매겨준다. 연도별로 주문수량을 같을 때는 가장 최근 연도를 출력해야하므로 총주문수량으로 내림차순 한 뒤 연도별로도 내림차순을 적용해준다.

WITH t1 AS (
    SELECT 
        sub.customerid
        , sub.customer_name
        , YEAR(s.orderdate) AS year
        , SUM(s.orderqty) AS total_orderqty
    FROM sales_order s
    JOIN
    (
        SELECT
            customerid
            , CONCAT_WS(' ', firstname, lastname) AS customer_name
        FROM customer
        WHERE customerid IN (SELECT customerid
                             FROM sales_order
                             GROUP BY customerid
                             HAVING MIN(orderdate) LIKE '2011-12%')
    ) sub
    ON s.customerid = sub.customerid
    GROUP BY customerid, year
) 
SELECT 
	*
    , RANK() OVER(PARTITION BY customer_id ORDER BY total_orderqty DESC, year DESC) AS qty_rank
FROM t1

 

3. 마지막으로 위 테이블에서 qty_rank가 1인 행을 필터링하고 customerid로 오름차순 정렬해준다.

WITH t1 AS (
    SELECT 
        sub.customerid
        , sub.customer_name
        , YEAR(s.orderdate) AS year
        , SUM(s.orderqty) AS total_orderqty
    FROM sales_order s
    JOIN
    (
        SELECT
            customerid
            , CONCAT_WS(' ', firstname, lastname) AS customer_name
        FROM customer
        WHERE customerid IN (SELECT customerid
                             FROM sales_order
                             GROUP BY customerid
                             HAVING MIN(orderdate) LIKE '2011-12%')
    ) sub
    ON s.customerid = sub.customerid
    GROUP BY customerid, year
), 
t2 AS (
SELECT 
	*
    , RANK() OVER(PARTITION BY customerid ORDER BY total_orderqty DESC, year DESC) AS qty_rank
FROM t1
)
SELECT
    customerid
    , customer_name
    , year AS max_qty_year
    , total_orderqty AS max_total_qty
FROM t2
WHERE qty_rank = 1
ORDER BY customerid

문제는 

- 월별(년-월) 주문 건수를 계산하되, 주문이 없는 달도 0건으로 포함하고

- 지난달 대비 주문 건수 증감율도 계산해야 하는 문제다

 

우선 주문 시간을 월별로 GROUP BY 한 뒤 주문건수를 구해보자.

 

16년 10월, 11월 데이터가 빠져있는 것을 확인할 수 있다.

빠진 월을 포함할 수 있도록 재귀 테이블을 만들어준다.

 

먼저 재귀테이블의 구조를 알아보자

 

이 구조에서 날짜값을 하나씩 더해갈 건데 초기값 2016-10 부터 한달씩 더해야 한다.

이때 DATE_ADD 함수가 쓰이는데 이 함수에 대해서도 알아 둘 필요가 있다.

 

이제 테이블을 만들어보자. DATE_ADD의 데이터로는 완전한 날짜 형식 (예: '2022-10-01') 이 들어가야 한다

 

테이블이 만들어졌으니 먼저 확인한 테이블과 현재 테이블 기준으로 LEFT JOIN 해주자

 

 

잘 만들어진걸 확인할 수 있다. COUNT(*)은 NULL인 값도 세므로 order_id를 세어준다

다음으로 지난 달 대비 증감율을 구해야 하는데, order_cnt 이전 행의 값을 가져와줘야 한다.

LAG 윈도우 함수를 이용해보자

 

윈도우 함수의 구조는 다음과 같다

LAG() 함수에 대해서도 알아보자. LAG 함수의 구조는 다음과 같다.

 

앞서 만든 테이블을 CTE로 보내 윈도우 함수를 적용해보자

 

 

order_cnt의 이전 행을 가져오는 컬럼을 만들었다. 이제 증감률을 계산할 차례이다

증감률은 다음과 같이 구한다

(현재 cnt - 이전 cnt) / 이전 cnt * 100

 

앞선 테이블을 서브쿼리로 보내 증감률 구할건데 컬럼 만들기 전에 처리해야 할 것이 있다.

이전 cnt 중에 0인 값이 있는데 0으로 나누게 되면 Division by 0 에러가 발생한다.

이를 처리하기 위해 이전행으로 나눌 때 IF문을 활용하여 0이면 1로 바꿔주자

 

 

완성이다

[문제]
USER_INFO 테이블과 ONLINE_SALE 테이블에서 2021년에 가입한 전체 회원들 중 상품을 구매한 회원수와 상품을 구매한 회원의 비율(=2021년에 가입한 회원 중 상품을 구매한 회원수 / 2021년에 가입한 전체 회원 수)을 년, 월 별로 출력하는 SQL문을 작성해주세요. 상품을 구매한 회원의 비율은 소수점 두번째자리에서 반올림하고, 전체 결과는 년을 기준으로 오름차순 정렬해주시고 년이 같다면 월을 기준으로 오름차순 정렬해주세요.


[단계별 풀이]
1. 두 테이블을 USER_ID로 JOIN 해준다. (SUB쿼리로 USER_ID를 필터링할 수도 있지만 성능상 좋지 않다)

2. 필터링은 LIKE 연산자로 해주는 것이 YEAR(JOINED) = 2021 보다 더 효율적이다. (문자열 단순 비교)

3. 연월로 GROUP BY 해준 뒤

4. DISTINCT를 사용해 중복을 제거한 구매자를 COUNT한다

5. 서브쿼리를 활용해 2021년에 가입한 전체 사용자를 COUNT 한다

6. 둘을 나눠서 구매한 회원 비율을 구해준다

7. 년과 월로 오름차순 정렬한다

 


[정답]

SELECT YEAR(SALES_DATE) YEAR,
       MONTH(SALES_DATE) MONTH,
       COUNT(DISTINCT S.USER_ID) AS PURCHASED_USERS,
       ROUND(COUNT(DISTINCT S.USER_ID) / (SELECT COUNT(USER_ID) 
                                        FROM USER_INFO
                                        WHERE JOINED LIKE '2021%'), 1) AS PUCHASED_RATIO
FROM ONLINE_SALE S
JOIN USER_INFO I
    ON S.USER_ID = I.USER_ID
WHERE I.JOINED LIKE '2021%'
GROUP BY YEAR, MONTH
ORDER BY YEAR, MONTH

[문제]
CAR_RENTAL_COMPANY_CAR 테이블과 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블과 CAR_RENTAL_COMPANY_DISCOUNT_PLAN 테이블에서 자동차 종류가 '트럭'인 자동차의 대여 기록에 대해서 대여 기록 별로 대여 금액(컬럼명: FEE)을 구하여 대여 기록 ID와 대여 금액 리스트를 출력하는 SQL문을 작성해주세요. 결과는 대여 금액을 기준으로 내림차순 정렬하고, 대여 금액이 같은 경우 대여 기록 ID를 기준으로 내림차순 정렬해주세요.


[단계별 풀이]
1. HISTORY 테이블과 CAR 테이블을 CAR_ID로 JOIN 하되 CAR_TYPE이 트럭인 행들만 필터링해서 JOIN 한다

2. DATE_DIFF를 사용하여 대여 기간을 구하고 기간별 할인율을 PLAN 테이블에서 확인해서 가져온다.

3. CASE WHEN 문으로 기간별로 할인율을 배정하는 컬럼을 만들어주고 서브쿼리로 보낸다 (기록ID, 하루요금, 기간, 기간별할인율)

4. 메인쿼리에서 기록ID와 대여금액을 구해준 뒤 출력한다

5. 요금과 ID로 내림차순 정렬한다.


[정답]

SELECT HISTORY_ID,
       ROUND(DAILY_FEE * PERIOD * (1-DISCOUNT_RATE)) AS FEE
FROM
(
    SELECT HISTORY_ID,
           DAILY_FEE,
           DATEDIFF(END_DATE, START_DATE) + 1 AS PERIOD,
           CASE 
               WHEN DATEDIFF(END_DATE, START_DATE) + 1 < 7 THEN 0
               WHEN DATEDIFF(END_DATE, START_DATE) + 1 < 30 THEN 0.05
               WHEN DATEDIFF(END_DATE, START_DATE) + 1 < 90 THEN 0.08
               ELSE 0.15
           END AS DISCOUNT_RATE
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY B
    JOIN CAR_RENTAL_COMPANY_CAR A
        ON B.CAR_ID = A.CAR_ID
            AND CAR_TYPE = '트럭'
) SUB
ORDER BY FEE DESC, HISTORY_ID DESC

[문제]
https://school.programmers.co.kr/learn/courses/30/lessons/157339

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

자동차 종류가 '세단' 또는 'SUV' 인 자동차 중 2022년 11월 1일부터 2022년 11월 30일까지 대여 가능하고 30일간의 대여 금액이 50만원 이상 200만원 미만인 자동차에 대해서 자동차 ID, 자동차 종류, 대여 금액(컬럼명: FEE) 리스트를 출력하는 SQL문을 작성해주세요. 결과는 대여 금액을 기준으로 내림차순 정렬하고, 대여 금액이 같은 경우 자동차 종류를 기준으로 오름차순 정렬, 자동차 종류까지 같은 경우 자동차 ID를 기준으로 내림차순 정렬해주세요.

 

[단계별 풀이]

1. 출력해야 하는 컬럼을 보자. 자동차 ID, 자동차 종류, 그리고 대여 금액을 구해야한다.

자동차 ID와 자동차 종류는 CAR_RENTAL_COMPANY_CAR 테이블에서 가져올 수 있고,

대여금액은 1일 가격과 기간, 할인율 정보가 필요한데  이는 

CAR_RENTAL_COMPANY_DISCOUNT_PLAN 에서 가져올 수 있다.

 

2. 두 테이블을 먼저 병합하자. 모든 자동차들에 대해서 출력해야 하므로 LEFT JOIN을 해도 되지만 두 테이블이 모든 타입정보를 포함하고 있으므로 INNER JOIN을 해도 된다. CAR_TYPE 기준으로 병합하자

병합한 테이블

3. 다음 조건을 보자. 

a. 자동차 종류가 세단 또는 SUV인 자동차를 필터링 해야하고,

b. 2022년 11월 달 내내 대여가 가능해야 하고

c. 30일 간의 대여 금액이 50만원 이상 200만원 미만이어야 한다.

 

a 번 조건은 앞서 테이블을 병합할 때 JOIN 조건에 추가해주자.

b 번 조건을 확인하기 위해서는 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 대여 기록이 정보를 가져와야 한다. 앞서 병합한 테이블과 또 다시 병합해주자. 기록이 없는 자동차들도 있을 수 있으므로 여기서는 LEFT JOIN을 해야 한다.

c 번 조건은 30일 간의 대여 금액을 구하는 것이므로 우리에게 필요한 할인율은 30일 이상에 해당하는 할인율이다. a번 조건과 함께 ON 조건절에서 처리해주자

JOIN조건 추가 및 LEFT JOIN

 

b 번 조건에서 22년 11월 달 내내 대여가 가능한 자동차 ID를 필터링하려면 어떻게 해야할까?

우선 테이블을 살펴보자. (C.CAR_ID, START_DATE, END_DATE 출력 H.CAR_ID 로 정렬)

 

대여 기록이 없는 차량도 있고 대여기록이 많은 차량도 있다. 여기서 어떻게  11월 달 풀로 대여가 가능한 차들만 필터링 할 수 있을까? 답은 11월 달에 빌린 기록이 있는 애들만 필터링하면 된다.

 

CAR_RENTAL_COMPANY_RENTAL_HISTORY  테이블에서 11월 기록이 있는 행들만 필터링하고 그 상태로 조인을 하게 된다면 11월 기록이 있는 차량들에 대해서는 정상적으로 연결이 되고, 그렇지 않은 차량들은 LEFT JOIN 이므로 NULL값이 된다. 11월 기록이 있는 차량들의 특징은 START_DATE 가 11월 30일보다 같거나 작으면서 END_DATE가 11월 1일보다 크거나 작아야 한다. 이를 ON 조건에 추가해주자.

 

11월 달에 빌린 기록이 있는 차량들만 필터링 되어서 LEFT JOIN으로 연결되었다. 대여 기록 정보가 NULL인 차량들이 바로 11월 달에 풀로 빌릴 수 있는 차량들이다. 이를 WHERE 절에서 필터링 해주자.  (START_DATE IS NULL)

 

이제 제일 처음 살펴보았던 컬럼을 출력해주자.

CAR_ID 와 CAR_TYPE, 30일간의 대여금액을 구해준다.

 

대여금액 = 1일 요금 x 30  x (1 - 할인율)  DISCOUNT_RATE : 8 → 0.08로 조정

 

대여금액에 별칭을 붙여주고 별칭은 HAVING 절에서 사용이 가능하니 HAVING 절에서 대여금액 조건을 걸어주고 정렬하고 제출하자.


[정답]

SELECT 
    C.CAR_ID
    , C.CAR_TYPE
    , ROUND(C.DAILY_FEE * 30 * (1 - P.DISCOUNT_RATE/100)) AS FEE
FROM CAR_RENTAL_COMPANY_CAR C
JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN P
    ON C.CAR_TYPE = P.CAR_TYPE
    AND C.CAR_TYPE IN ('SUV', '세단')
    AND P.DURATION_TYPE = '30일 이상'
LEFT JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY H
    ON C.CAR_ID = H.CAR_ID
    AND H.START_DATE <= '2022-11-30'
    AND H.END_DATE >= '2022-11-01'
WHERE H.START_DATE IS NULL
HAVING FEE >= 500000 AND FEE < 2000000
ORDER BY FEE DESC, CAR_TYPE, CAR_ID DESC

[문제]
보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.


[단계별 풀이]
해당 문제는 이빠진 데이터를 채워야하는 문제로 재귀저문제]

보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.

 

 

[단계별 풀이]

해당 문제는 이빠진 데이터를 채워야하는 문제로 재귀테이블을 사용해야한다

구조를 알아보자

WITH RECURSIVE 테이블명 (컬럼명) AS (
    SELECT 초기값
    UNION ALL
    SELECT 반복할 쿼리 -- 이전값에 대해 쿼리 적용
    WHERE 반복 조건 -- FALSE가 나오면 반복종료, WHERE/LIMIT 등 사용하면 됨
)
SELECT *
FROM 테이블명

 

1. 재귀 테이블을 활용해서 0부터 23까지 시간데이터를 만든다

2. 마찬가지로 OUTS 테이블에서 HOUR 컬럼을 만든다 (만드는 김에 HOUR로 GROUP BY 해서 COUNT도 구해준다)

3. 재귀 테이블을 기준으로 LEFT JOIN 한다

4. HOUR와 COUNT 컬럼을 조회하되 COUNT컬럼의 NULL값을 0으로 대체한다

5. HOUR를 기준으로 오름차순 정렬한다

 

 

[정답]

WITH RECURSIVE HOUR_CTE (HOUR) AS (
    SELECT 0 
    UNION ALL
    SELECT HOUR + 1
    FROM HOUR_CTE
    WHERE HOUR < 23
)
SELECT H.HOUR,
       IFNULL(COUNT, 0) AS COUNT
FROM HOUR_CTE H
LEFT JOIN (SELECT HOUR(DATETIME) HOUR,
                  COUNT(ANIMAL_ID) COUNT
           FROM ANIMAL_OUTS
           GROUP BY 1) SUB
ON H.HOUR = SUB.HOUR

[문제]
USED_GOODS_BOARD와 USED_GOODS_REPLY 테이블에서 2022년 10월에 작성된 게시글 제목, 게시글 ID, 댓글 ID, 댓글 작성자 ID, 댓글 내용, 댓글 작성일을 조회하는 SQL문을 작성해주세요. 결과는 댓글 작성일을 기준으로 오름차순 정렬해주시고, 댓글 작성일이 같다면 게시글 제목을 기준으로 오름차순 정렬해주세요.


[단계별 풀이]
1. 두 테이블을 BOARD_ID로 JOIN

2. 게시글 작성일자가 2022년 10월인 행들만 필터링
3. 제목, 게시글 ID, 댓글 ID, 댓글 작성자 ID, 댓글 내용, 댓글 작성일을 조회

4. 댓글 작성일, 제목을 오름차순 정렬

 


[정답]

SELECT B.TITLE, 
       B.BOARD_ID, 
       R.REPLY_ID,
       R.WRITER_ID,
       R.CONTENTS,
       DATE_FORMAT(R.CREATED_DATE, '%Y-%m-%d') CREATED_DATE
FROM USED_GOODS_BOARD B
JOIN USED_GOODS_REPLY R
    ON B.BOARD_ID = R.BOARD_ID
WHERE B.CREATED_DATE LIKE '2022-10%'
ORDER BY CREATED_DATE, TITLE

[문제]
ONLINE_SALE 테이블과 OFFLINE_SALE 테이블에서 2022년 3월의 오프라인/온라인 상품 판매 데이터의 판매 날짜, 상품ID, 유저ID, 판매량을 출력하는 SQL문을 작성해주세요. OFFLINE_SALE 테이블의 판매 데이터의 USER_ID 값은 NULL 로 표시해주세요. 결과는 판매일을 기준으로 오름차순 정렬해주시고 판매일이 같다면 상품 ID를 기준으로 오름차순, 상품ID까지 같다면 유저 ID를 기준으로 오름차순 정렬해주세요.


[단계별 풀이]
1. 두 테이블을 판매날짜 기준으로 합하되 FULL OUTER JOIN을 하자

2. LEFT JOIN과 RIGHT JOIN을 UNION 해주자

3. 이때 OFF 테이블의 USER_ID는 NULL 처리 해준다

4. 판매 날짜, 상품ID, 유저ID, 판매량을 출력한다

5. 판매일, 상품 ID, 유저ID를 오름차순으로 정렬한다.


[정답]

SELECT DATE_FORMAT(SALES_DATE, '%Y-%m-%d') AS SALES_DATE,
       PRODUCT_ID,
       USER_ID,
       SALES_AMOUNT
FROM ONLINE_SALE 
WHERE SALES_DATE LIKE '2022-03%'
UNION ALL
SELECT DATE_FORMAT(SALES_DATE, '%Y-%m-%d'),
       PRODUCT_ID,
       NULL,
       SALES_AMOUNT
FROM OFFLINE_SALE
WHERE SALES_DATE LIKE '2022-03%'
ORDER BY 1, 2, 3

[문제]
FOOD_FACTORY 테이블에서 강원도에 위치한 식품공장의 공장 ID, 공장 이름, 주소를 조회하는 SQL문을 작성해주세요. 이때 결과는 공장 ID를 기준으로 오름차순 정렬해주세요.


[단계별 풀이]

1. ADDRESS가 강원인 행을 필터링 (LIKE연산자)

2. ID, NAME, ADDRESS 출력

3. ID로 오름차순 정렬



[정답]

SELECT FACTORY_ID, 
       FACTORY_NAME,
       ADDRESS
FROM FOOD_FACTORY
WHERE ADDRESS LIKE '강원%'
ORDER BY FACTORY_ID

[문제]
MEMBER_PROFILE와 REST_REVIEW 테이블에서 리뷰를 가장 많이 작성한 회원의 리뷰들을 조회하는 SQL문을 작성해주세요. 회원 이름, 리뷰 텍스트, 리뷰 작성일이 출력되도록 작성해주시고, 결과는 리뷰 작성일을 기준으로 오름차순, 리뷰 작성일이 같다면 리뷰 텍스트를 기준으로 오름차순 정렬해주세요.


[단계별 풀이]
1. 우선 리뷰 MEMBER_ID 로 GROUP BY 해서 REVIEW 의 갯수를 구한다. 정렬하고 1행만 남겨둔다

2. 해당 쿼리를 서브쿼리로 보내고

3. 멤버테이블과 리뷰테이블을 MEMBER_ID로 JOIN

4. 이름과 리뷰텍스트, 작성일을 조회한다

5. 아까 보낸 서브쿼리서 MEMBER_ID를 가져와 같은 것들만 필터링

6. 정렬


[정답]

SELECT
    M.MEMBER_NAME,
    R.REVIEW_TEXT,
    DATE_FORMAT(R.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE M
JOIN REST_REVIEW R
    ON M.MEMBER_ID = R.MEMBER_ID
WHERE M.MEMBER_ID = (SELECT MEMBER_ID
                     FROM REST_REVIEW
                     GROUP BY MEMBER_ID
                     ORDER BY COUNT(REVIEW_ID) DESC
                     LIMIT 1)
ORDER BY REVIEW_DATE, REVIEW_TEXT

+ Recent posts