제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit(GROUP BY)입니다.

노선별 평균 역 사이 거리 조회하기

SELECT
    ROUTE,
    CONCAT(ROUND(SUM(D_BETWEEN_DIST), 1), 'km') AS TOTAL_DISTANCE,
    CONCAT(ROUND(AVG(D_BETWEEN_DIST), 2), 'km') AS AVERAGE_DISTANCE
FROM SUBWAY_DISTANCE
GROUP BY ROUTE
ORDER BY SUM(D_BETWEEN_DIST) DESC;
  • 노선 별로 구하기 위해 ROUTE를 그룹화합니다.
    GROUP BY ROUTE
  • 총 누계거리와 평균 역사이를 구하기 위해 SUM과 AVG 함수를 사용하고 문자열을 합성하기 위해 CONCAT 함수를 사용합니다.
    CONCAT(ROUND(SUM(D_BETWEEN_DIST), 1), 'km') AS TOTAL_DISTANCE,
    CONCAT(ROUND(AVG(D_BETWEEN_DIST), 2), 'km') AS AVERAGE_DISTANCE
  • 총 누계거리를 기준으로 내림차순 정렬합니다.

물고기 종류 별 잡은 수 구하기

SELECT COUNT(*) AS FISH_COUNT, FISH_NAME
FROM FISH_INFO A
JOIN FISH_NAME_INFO B
  ON A.FISH_TYPE = B.FISH_TYPE
GROUP BY FISH_NAME
ORDER BY 1 DESC
  • 잡은 물고기와 이름을 매핑하기 위해 JOIN 합니다.
    JOIN FISH_NAME_INFO B ON A.FISH_TYPE = B.FISH_TYPE
  • 물고기 종류를 위해 그룹화합니다.
    GROUP BY FISH_NAME
  • 물고기 잡은 수를 기준으로 내림차순 정렬합니다.

월별 잡은 물고기 수 구하기

SELECT
    COUNT(*) AS FISH_COUNT,
    EXTRACT(MONTH FROM TIME) AS MONTH
FROM FISH_INFO
GROUP BY EXTRACT(MONTH FROM TIME)
ORDER BY EXTRACT(MONTH FROM TIME) ASC
  • 월별로 잡은 물고기를 구하기 위해 그룹화합니다.
    GROUP BY EXTRACT(MONTH FROM TIME)
  • 월을 기준으로 오름차순 정렬합니다.

특정 조건을 만족하는 물고기 별 수와 최대 길이 구하기

SELECT
    COUNT(FISH_TYPE) AS FISH_COUNT,
    MAX(LENGTH) AS MAX_LENGTH,
    FISH_TYPE
FROM (
    SELECT
        ID,
        FISH_TYPE,
        IFNULL(LENGTH, 10) AS LENGTH
    FROM FISH_INFO
) F
GROUP BY FISH_TYPE
HAVING AVG(LENGTH) >= 33
ORDER BY FISH_TYPE ASC;
  • 길이가 10 이하면 null이므로 null을 10으로 지정하기 위해 IFNULL 함수를 사용한 서브 테이블을 F로 지정합니다.
    (
        SELECT
            ID,
            FISH_TYPE,
            IFNULL(LENGTH, 10) AS LENGTH
        FROM FISH_INFO
    ) F
  • 평균 길이가 33인 물고기 종류 별로 그룹화합니다.
    GROUP BY FISH_TYPE
    HAVING AVG(LENGTH) >= 33
  • 최대 길이와 물고기 잡은 수를 위해 COUNT 함수와 MAX 함수를 사용합니다.
  • 물고기 종류를 기준으로 오름차순 정렬합니다.
제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit(GROUP BY)입니다.

고양이와 개는 몇마리 있을까

SELECT
    ANIMAL_TYPE,
    COUNT(*) AS COUNT
FROM ANIMAL_INS
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE
  • 고양이와 개를 그룹화합니다.
    GROUP BY ANIMAL_TYPE
  • 개수를 구하기 위해 COUNT 함수를 사용하고 고양이가 먼저 나오기 위해 오름차순 정렬합니다.

동명 동물 수 찾기

SELECT
    NAME,
    COUNT(*) AS COUNT
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT(*) > 1
ORDER BY NAME
  • 이름이 있으며, 이름을 기준으로 그룹화합니다.
    WHERE NAME IS NOT NULL
    GROUP BY NAME
  • 동일한 이름의 동물을 찾기 위해 HAVING 절을 통해 COUNT 함수를 사용합니다.
    HAVING COUNT(*) > 1
  • 동물 이름을 기준으로 오름차순 정렬합니다.

년, 월, 성별 별 상품 구매 회원 수 구하기

SELECT
    TO_CHAR(O.SALES_DATE, 'YYYY') AS YEAR, 
    EXTRACT(MONTH FROM O.SALES_DATE) AS MONTH, 
    U.GENDER AS GENDER,
    COUNT(DISTINCT U.USER_ID) AS USERS
FROM USER_INFO U JOIN ONLINE_SALE O
ON U.USER_ID = O.USER_ID
WHERE U.GENDER IS NOT NULL
GROUP BY TO_CHAR(O.SALES_DATE, 'YYYY'), EXTRACT(MONTH FROM O.SALES_DATE), U.GENDER
ORDER BY TO_CHAR(O.SALES_DATE, 'YYYY'), EXTRACT(MONTH FROM O.SALES_DATE), U.GENDER
  • 상품 구매한 회원을 구하기 위해 JOIN합니다.
    FROM USER_INFO U JOIN ONLINE_SALE O ON U.USER_ID = O.USER_ID
  • 성별 정보가 없는 데이터는 제외하기 위해 조건을 걸어줍니다.
    WHERE U.GENDER IS NOT NULL
  • 연도, 월, 성별을 기준으로 그룹화 및 정렬합니다.
    GROUP BY TO_CHAR(O.SALES_DATE, 'YYYY'), EXTRACT(MONTH FROM O.SALES_DATE), U.GENDER
    ORDER BY TO_CHAR(O.SALES_DATE, 'YYYY'), EXTRACT(MONTH FROM O.SALES_DATE), U.GENDER

입양 시각 구하기(1)

SELECT 
    TO_NUMBER(TO_CHAR(DATETIME, 'HH24') AS HOUR,
    COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE TO_CHAR(DATETIME, 'HH24') BETWEEN 09 AND 19
GROUP BY TO_CHAR(DATETIME, 'HH24')
ORDER BY HOUR ASC
  • 09시와 19시 사이의 데이터를 조회하기 위해 TO_CHAR와 BETWEEN 함수를 사용합니다.
    WHERE TO_CHAR(DATETIME, 'HH24') BETWEEN 09 AND 19
  • 입양 시각을 기준으로 그룹화합니다.
    GROUP BY TO_CHAR(DATETIME, 'HH24')
  • 정렬하기 위해 TO_NUMBER 함수를 사용하고 HOUR를 기준으로 오름차순 정렬합니다.

입양 시각 구하기(2)

SELECT 
    L.HOUR AS HOUR, 
    NVL(COUNT, 0) AS COUNT
FROM (
    SELECT TO_CHAR(DATETIME, 'HH24') AS HOUR, COUNT(*) AS COUNT 
    FROM ANIMAL_OUTS 
    GROUP BY TO_CHAR(DATETIME, 'HH24') 
    ORDER BY HOUR
) O, (
    SELECT LEVEL -1 AS HOUR 
    FROM DUAL 
    CONNECT BY LEVEL <= 24
) L      
WHERE L.HOUR = O.HOUR(+)
ORDER BY L.HOUR;
  • 입양 시각을 통해 그룹화를 진행합니다.
    (
        SELECT TO_CHAR(DATETIME, 'HH24') AS HOUR, COUNT(*) AS COUNT 
        FROM ANIMAL_OUTS 
        GROUP BY TO_CHAR(DATETIME, 'HH24') 
        ORDER BY HOUR
    ) O
  • 가상의 테이블와 계층 쿼리를 통해 LEVEL을 0부터 23까지 숫자를 반환합니다.
    ( SELECT LEVEL -1 AS HOUR FROM DUAL CONNECT BY LEVEL <= 24 ) L
  • O 테이블과 L 테이블을 LEFT OUTER JOIN합니다. 레코드가 없는 행을 0으로 표현하기 위함입니다.
    WHERE L.HOUR = O.HOUR(+)
  • NULL인 데이터를 0으로 표현하기 위해 NVL함수를 사용하고 HOUR를 기준으로 오름차순 정렬합니다.
    NVL(COUNT, 0) AS COUNT

가격대 별 상품 개수 구하기

SELECT
    FLOOR(PRICE / 10000) * 10000 AS PRICE_GROUP,
    COUNT(*)
FROM PRODUCT
GROUP BY FLOOR(PRICE / 10000) * 10000
ORDER BY PRICE_GROUP
  • 만원 단위의 가격대로 표현하기 위해 버림과 10000 곱하기를 통해 그룹화합니다.
    GROUP BY FLOOR(PRICE / 10000) * 10000
  • 가격대를 기준으로 오름차순 정렬합니다.

언어별 개발자 분류하기

WITH J AS (
    SELECT 
        ID,
        EMAIL,
        CASE -- 조건에 맞게 SCORE를 기록
           WHEN COUNT(CASE WHEN CATEGORY = 'Front End' THEN 1 END) > 0 AND 
                COUNT(CASE WHEN NAME = 'Python' THEN 1 END) > 0 
                THEN 3
           WHEN COUNT(CASE WHEN NAME = 'C#' THEN 1 END) > 0 THEN 2
           WHEN COUNT(CASE WHEN CATEGORY = 'Front End' THEN 1 END) > 0 THEN 1
        END AS SCORE
    FROM
        DEVELOPERS AS D
    JOIN -- 비트 논리 연산을 조건으로 JOIN
        SKILLCODES AS S ON D.SKILL_CODE & S.CODE
    GROUP BY 
        ID,EMAIL
    HAVING 
        SCORE > 0
)
SELECT 
    CASE 
        WHEN SCORE = 3 THEN 'A'
        WHEN SCORE = 2 THEN 'B'
        WHEN SCORE = 1 THEN 'C'
    END AS GRADE,
    ID,
    EMAIL
FROM 
    J
ORDER BY 
    1,2
  • DEVELOPERS 테이블의 SKILL_CODE와 SKILLCODES 테이블의 CODE 값을 비트 논리 AND 연산(&)을 통해 조건에 맞는 조인을 수행
    FROM DEVELOPERS AS D JOIN SKILLCODES AS S ON D.SKILL_CODE & S.CODE
  • ID와 EMAIL을 통해 그룹화 합니다.
    GROUP BY ID, EMAIL
  • SCORE는 0보다 큰 것들만 조회합니다.
    HAVING SCORE > 0
  • 개발자의 점수를 결정하기 위해 CASE 문을 사용합니다.
  • WITH 절을 이용합니다.
  • CASE 절을 통해 A, B, C를 결정합니다.
    CASE 
            WHEN SCORE = 3 THEN 'A'
            WHEN SCORE = 2 THEN 'B'
            WHEN SCORE = 1 THEN 'C'
        END AS GRADE,
  • GRADE와 ID를 통해 오름차순 정렬합니다.

조건에 맞는 사원정보 조회하기

SELECT
    G.SCORE,
    G.EMP_NO,
    E.EMP_NAME,
    E.POSITION,
    E.EMAIL
FROM (
    SELECT
        EMP_NO,
        SUM(SCORE) AS SCORE
    FROM HR_GRADE
    GROUP BY EMP_NO, YEAR
    ORDER BY SCORE DESC
    LIMIT 1
) G
JOIN HR_EMPLOYEES E ON G.EMP_NO = E.EMP_NO;
  • 사원 정보와 연도를 기준으로 GROUP화하여 SCORE가 가장 높은 사원을 조회하는 서브 테이블을 G로 설정합니다.
    (
        SELECT
            EMP_NO,
            SUM(SCORE) AS SCORE
        FROM HR_GRADE
        GROUP BY EMP_NO, YEAR
        ORDER BY SCORE DESC
        LIMIT 1
    ) G
  • HR_EMPLOYEES 와 회원 넘버를 통해 JOIN합니다.
    FROM (...) G JOIN HR_EMPLOYEES E ON G.EMP_NO = E.EMP_NO

연간 평가 점수에 해당하는 평가 등급 및 성과금 조회하기

SELECT
    G.EMP_NO,
    E.EMP_NAME,
    CASE
        WHEN G.SCORE / 2 >= 96 THEN 'S'
        WHEN G.SCORE / 2 >= 90 THEN 'A'
        WHEN G.SCORE / 2 >= 80 THEN 'B' 
        ELSE 'C'
    END AS GRADE,
    E.SAL * CASE
        WHEN G.SCORE / 2 >= 96 THEN 0.2
        WHEN G.SCORE / 2 >= 90 THEN 0.15
        WHEN G.SCORE / 2 >= 80 THEN 0.1
        ELSE 0
    END AS BONUS
FROM (
    SELECT
        EMP_NO,
        SUM(SCORE) AS SCORE
    FROM HR_GRADE
    GROUP BY EMP_NO, YEAR
    ORDER BY SCORE DESC
) G
JOIN HR_EMPLOYEES E ON G.EMP_NO = E.EMP_NO
ORDER BY G.EMP_NO;
  • 사원 정보와 연도를 기준으로 GROUP화하여 합산 SCORE 사원을 조회하는 서브 테이블을 G로 설정합니다.
    (
        SELECT
            EMP_NO,
            SUM(SCORE) AS SCORE
        FROM HR_GRADE
        GROUP BY EMP_NO, YEAR
        ORDER BY SCORE DESC
    ) G
  • HR_EMPLOYEES 와 회원 넘버를 통해 JOIN합니다.
    FROM (...) G JOIN HR_EMPLOYEES E ON G.EMP_NO = E.EMP_NO
  • CASE 절을 통해 성과금과 평가등급을 설정합니다.
    CASE
            WHEN G.SCORE / 2 >= 96 THEN 'S'
            WHEN G.SCORE / 2 >= 90 THEN 'A'
            WHEN G.SCORE / 2 >= 80 THEN 'B' 
            ELSE 'C'
        END AS GRADE,
        E.SAL * CASE
            WHEN G.SCORE / 2 >= 96 THEN 0.2
            WHEN G.SCORE / 2 >= 90 THEN 0.15
            WHEN G.SCORE / 2 >= 80 THEN 0.1
            ELSE 0
        END AS BONUS

부서별 평균 연봉 조회하기

SELECT
    E.DEPT_ID,
    D.DEPT_NAME_EN,
    E.AVG_SAL
FROM HR_DEPARTMENT D JOIN (
    SELECT
        DEPT_ID,
        ROUND(AVG(SAL)) AS AVG_SAL
    FROM HR_EMPLOYEES
    GROUP BY DEPT_ID
) E ON D.DEPT_ID = E.DEPT_ID
ORDER BY E.AVG_SAL DESC
  • 부서 아이디를 통해 그룹화하여 평균 연봉을 서브테이블 E로 구합니다.
    (
        SELECT
            DEPT_ID,
            ROUND(AVG(SAL)) AS AVG_SAL
        FROM HR_EMPLOYEES
        GROUP BY DEPT_ID
    ) E
  • HR_DEPARTMENT 테이블과 E 테이블을 부서 아이디를 통해 JOIN합니다.
    FROM HR_DEPARTMENT D JOIN (...) E ON D.DEPT_ID = E.DEPT_ID
  • 평균 연봉을 통해 내림차순 정렬합니다.
제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
Programmers SQL 고득점 Kit(GROUP BY)입니다.

카테고리 별 도서 판매량 집계하기

SELECT 
    B.CATEGORY,
    SUM(S.SALES)
FROM BOOK B JOIN (
    SELECT *
    FROM BOOK_SALES
    WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
) S
ON B.BOOK_ID = S.BOOK_ID
GROUP BY B.CATEGORY
ORDER BY B.CATEGORY
  • 2022년 1월에 판매된 레코드를 조회합니다. (테이블 S)
(
    SELECT *
    FROM BOOK_SALES
    WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
) S
  • BOOK 테이블과 BOOK_ID를 기준으로 JOIN합니다.
    (FROM BOOK B JOIN (...) S ON B.BOOK_ID = S.BOOK_ID)
  • 카테고리를 기준으로 GROUP BY 해줍니다.
    (GROUP BY B.CATEGORY)
  • 판매량의 합계를 위해 SUM 함수를 사용하고 CATEGORY를 오름차순으로 정렬합니다.

저자 별 카테고리 별 매출액 집계하기

SELECT 
    A.AUTHOR_ID, 
    A.AUTHOR_NAME, 
    O.CATEGORY, 
    O.TOTAL_SALES
FROM AUTHOR A JOIN (
    SELECT 
        B.AUTHOR_ID, 
        B.CATEGORY, 
        SUM(B.PRICE * BS.SALES) AS TOTAL_SALES
    FROM BOOK B JOIN (
        SELECT BOOK_ID, SUM(SALES) AS SALES
        FROM BOOK_SALES
        WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
        GROUP BY BOOK_ID
    )BS ON B.BOOK_ID = BS.BOOK_ID
    GROUP BY AUTHOR_ID, B.CATEGORY
) O ON A.AUTHOR_ID = O.AUTHOR_ID
ORDER BY AUTHOR_ID, CATEGORY DESC
  • 2022년 1월에 판매된 책의 BOOK_ID와 판매량의 합계를 조회합니다.(테이블 BS)
(
    SELECT BOOK_ID, SUM(SALES) AS SALES
    FROM BOOK_SALES
    WHERE TO_CHAR(SALES_DATE, 'YYYY-MM') = '2022-01'
    GROUP BY BOOK_ID
)BS
  • BS 테이블과 BOOK 테이블과 BOOK_ID를 기준으로 조인합니다.
    (FROM BOOK B JOIN (...) BS ON B.BOOK_ID = BS.BOOK_ID)
  • 저자별, 카테고리별 그룹화를 해줍니다.
    (GROUP BY AUTHOR_ID, B.CATEGORY)
  • 판매량과 가격을 기준으로 TOTAL_SLAES를 구합니다.
    (SUM(B.PRICE * BS.SALES) AS TOTAL_SALES)
  • 해당 결과를 구한 테이블 O와 AUTHOR 테이블을 AUTHOR_ID를 기준으로 조인합니다.
    (FROM AUTHOR A JOIN (...) O ON A.AUTHOR_ID = O.AUTHOR_ID)
  • AUTHOR_ID를 오름차순으로, 카테고리를 내림차순으로 정렬합니다.

식품분류별 가장 비싼 식품의 정보 조회하기

SELECT
    F1.CATEGORY,
    F2.MAX_PRICE,
    F1.PRODUCT_NAME
FROM FOOD_PRODUCT F1 JOIN (
    SELECT
        CATEGORY,
        MAX(PRICE) AS MAX_PRICE
    FROM FOOD_PRODUCT F2
    GROUP BY CATEGORY
    HAVING CATEGORY IN ('과자', '국', '김치', '식용유')
)F2 ON F1.PRICE = F2.MAX_PRICE AND F1.CATEGORY IN ('과자', '국', '김치', '식용유')
ORDER BY F2.MAX_PRICE DESC
  • 식품 분류를 통해 그룹화를 합니다.
    (GROUP BY CATEGORY)
  • 식품 분류에는 '과자', '국', '김치', '식용유' 만 가능하기에 그룹화에서 HAVING절을 이용합니다.
    (HAVING CATEGORY IN ('과자', '국', '김치', '식용유'))
  • 그룹화한 테이블에서 각 식품 분류 별 가장 가격이 높은 필드를 선택하고 F2라는 테이블의 별칭을 설정합니다.
(
    SELECT
        CATEGORY,
        MAX(PRICE) AS MAX_PRICE
    FROM FOOD_PRODUCT F2
    GROUP BY CATEGORY
    HAVING CATEGORY IN ('과자', '국', '김치', '식용유')
)F2
  • FOOD_PRODUCT와 F2 테이블에서 가장 비싼 가격과 일치하고 식품 분류를 기준으로 JOIN합니다.
    (FROM FOOD_PRODUCT F1 JOIN (...) F2 ON F1.PRICE = F2.MAX_PRICE AND
    F1.CATEGORY IN ('과자', '국', '김치', '식용유'))
  • 식품 가격을 기준으로 내림차순 정렬합니다.

즐겨찾기가 가장 많은 식당 정보 출력하기

SELECT
    B.FOOD_TYPE,
    A.REST_ID,
    A.REST_NAME,
    B.FAVORITES
FROM REST_INFO A JOIN (
    SELECT
        FOOD_TYPE,
        MAX(FAVORITES) AS FAVORITES
    FROM REST_INFO
    GROUP BY FOOD_TYPE
)B ON A.FAVORITES = B.FAVORITES AND A.FOOD_TYPE = B.FOOD_TYPE
ORDER BY FOOD_TYPE DESC
  • 음식 종류를 기준으로 그룹화를 진행한 후 즐겨찾기가 가장 많은 음식 종류를 구한 테이블을 B라고 지정합니다.
(
    SELECT
        FOOD_TYPE,
        MAX(FAVORITES) AS FAVORITES
    FROM REST_INFO
    GROUP BY FOOD_TYPE
)B
  • REST_INFO 테이블과 B 테이블의 즐겨찾기 수와 음식 종류를 기준으로 JOIN합니다.
    (FROM REST_INFO A JOIN (...)B ON A.FAVORITES = B.FAVORITES AND A.FOOD_TYPE = B.FOOD_TYPE)
  • 음식 종류를 기준으로 내림차순 정렬합니다.

자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기

SELECT
    CAR_ID,
    MAX(
            CASE WHEN '2022-10-16' BETWEEN TO_CHAR(START_DATE,'YYYY-MM-DD') AND TO_CHAR(END_DATE,'YYYY-MM-DD') THEN '대여중'
                 ELSE '대여 가능'
                END) AS AVAILABILITY
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
ORDER BY CAR_ID DESC
  • CAR_ID를 기준으로 그룹화합니다.
    (GROUP BY CAR_ID)
  • 2022년 10월 16일을 기준으로 대여중인 차는 대여중, 대여중이지 않은 차는 대여 가능으로 표시하기 위해 CASE 절을 사용합니다.
    시작일자가 대여 가능보다 대여중이 우선적으로 선택하기 위해 MAX 함수를 사용합니다.
    (MAX(CASE WHEN '2022-10-16' BETWEEN TO_CHAR(START_DATE,'YYYY-MM-DD') AND TO_CHAR(END_DATE,'YYYY-MM-DD') THEN '대여중' ELSE '대여 가능' END) AS AVAILABILITY)
  • CAR_ID를 기준으로 내림차순 정렬합니다.

대여횟수가 많은 자동차들의 월별 대여 횟수 구하기

SELECT
    EXTRACT(MONTH FROM S.START_DATE) AS MONTH,  -- 월을 숫자로 바로 추출
    S.CAR_ID,
    COUNT(*) AS RECORDS
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY S
JOIN (
    SELECT 
        CAR_ID
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
    WHERE TO_CHAR(START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10'
    GROUP BY CAR_ID
    HAVING COUNT(*) >= 5
) R ON S.CAR_ID = R.CAR_ID
WHERE TO_CHAR(S.START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10'
GROUP BY EXTRACT(MONTH FROM S.START_DATE), S.CAR_ID
ORDER BY EXTRACT(MONTH FROM S.START_DATE) ASC, S.CAR_ID DESC;
  • 2022년 8월부터 10월까지 대여횟수가 5회 이상인 자동차를 구하기 위해 CAR_ID를 기준으로 그룹화 한 후 HAVING 절을 통해 조건을 걸어 서브 테이블 R을 생성합니다.
(
    SELECT 
        CAR_ID
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
    WHERE TO_CHAR(START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10'
    GROUP BY CAR_ID
    HAVING COUNT(*) >= 5
) R
  • CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 CAR_ID를 기준으로 R과 JOIN합니다.
    (FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY S JOIN (...) R ON S.CAR_ID = R.CAR_ID)
  • JOIN 조건에는 맞지만 START_DATE의 조건을 위해 한번 더 걸어줍니다.
    (WHERE TO_CHAR(S.START_DATE, 'YYYY-MM') BETWEEN '2022-08' AND '2022-10')
  • 대여 월과 CAR_ID를 기준으로 그룹화합니다.
    월을 구하는 방법에는 EXTRACT(MONTH FROM S.START_DATE)를 이용합니다. => 숫자만 추출하기 위함입니다.
    (GROUP BY EXTRACT(MONTH FROM S.START_DATE), S.CAR_ID)
  • 월을 기준으로 오름차순 정렬하고 자동차 ID를 기준으로 내림차순 정렬합니다.

자동차 종류 별 특정 옵션이 포함된 자동차 수 구하기

SELECT
    CAR_TYPE,
    COUNT(*) AS CARS
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%통풍시트%' 
   OR OPTIONS LIKE '%열선시트%' 
   OR OPTIONS LIKE '%가죽시트%'
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE ASC;
  • OPTION이 '통풍시트', '열선시트', '가죽시트'를 구하기 위해 like절을 이용합니다. (OPTIONS가 VARCHAR로 이루어져있기 때문에 like 절을 통해 조회합니다)
    (WHERE OPTIONS LIKE '%통풍시트%' 
       OR OPTIONS LIKE '%열선시트%' 
       OR OPTIONS LIKE '%가죽시트%')
  • 자동차 종류 별로 묶기 위해 그룹화합니다.
    (GROUP BY CAR_TYPE)
  • 자동차 종류를 기준으로 오름차순 정렬합니다.

성분으로 구분한 아이스크림 총 주문량

SELECT
    I.INGREDIENT_TYPE,
    SUM(F.TOTAL_ORDER) AS TOTAL_ORDER
FROM FIRST_HALF F JOIN ICECREAM_INFO I
ON F.FLAVOR = I.FLAVOR
GROUP BY I.INGREDIENT_TYPE
ORDER BY TOTAL_ORDER ASC;
  • 상반기 주문정보와 아이스크림 정보를 FLAVOR를 통해 JOIN합니다.
    (FROM FIRST_HALF F JOIN ICECREAM_INFO I ON F.FLAVOR = I.FLAVOR)
  • 아이스크림 맛을 기준으로 그룹화합니다.
    (GROUP BY I.INGREDIENT_TYPE)
  • 상반기 아이스크림 총 주문량의 합을 위해 SUM 함수를 사용하고 총 주문량를 기준으로 오름차순 정렬합니다.

진료과별 총 예약 횟수 출력하기

SELECT
    MCDP_CD AS "진료과 코드", 
    COUNT(*) AS "5월예약건수"
FROM APPOINTMENT
WHERE TO_CHAR(APNT_YMD, 'YYYY-MM') = '2022-05'
GROUP BY MCDP_CD
ORDER BY "5월예약건수", "진료과 코드"
  • 2022년 05월에 예약한 환자를 위해 테이블에 조건을 걸어줍니다.
    (WHERE TO_CHAR(APNT_YMD, 'YYYY-MM') = '2022-05')
  • 진료과 별로 그룹화하기 위해 MCDP_CD를 기준으로 그룹화합니다.
    (GROUP BY MCDP_CD)
  • 예약 수를 구하기 위해 COUNT 함수를 사용하고 예약 수와 진료과 코드를 기준으로 오름차순 정렬합니다.

조건에 맞는 사용자와 총 거래금액 조회하기

SELECT
    U.USER_ID,
    U.NICKNAME,
    R.TOTAL_SALES
FROM USED_GOODS_USER U JOIN (
    SELECT
        WRITER_ID,
        SUM(PRICE) AS TOTAL_SALES
    FROM USED_GOODS_BOARD B
    WHERE B.STATUS = 'DONE'
    GROUP BY WRITER_ID
    HAVING SUM(PRICE) >= 700000
)R ON U.USER_ID = R.WRITER_ID
ORDER BY R.TOTAL_SALES
  • 완료된 중고거래에서 회원별 중고 물품을 판매한 총 금액이 70만원이 넘는 레코드를 조회하기 위해 서브 테이블 R을 생성합니다.
(
    SELECT
        WRITER_ID,
        SUM(PRICE) AS TOTAL_SALES
    FROM USED_GOODS_BOARD B
    WHERE B.STATUS = 'DONE'
    GROUP BY WRITER_ID
    HAVING SUM(PRICE) >= 700000
)R
  • USED_GOODS_BOARD B와 R에 회원 아이디를 기준으로 JOIN합니다.
    (FROM USED_GOODS_USER U JOIN (...)R ON U.USER_ID = R.WRITER_ID)
  • 총 판매액을 기준으로 오름차순 정렬합니다.

+ Recent posts