Daily SQL Query by programmers (Level 3)

솔비·2024년 4월 22일
0

[4월 22일]

- 대장균의 크기에 따라 분류하기 1

문제
대장균 개체의 크기가 100 이하라면 'LOW', 100 초과 1000 이하라면 'MEDIUM', 1000 초과라면 'HIGH' 라고 분류합니다. 대장균 개체의 ID(ID) 와 분류(SIZE)를 출력하는 SQL 문을 작성해주세요.이때 결과는 개체의 ID 에 대해 오름차순 정렬해주세요.

SELECT ID
    , CASE WHEN SIZE_OF_COLONY <= 100 THEN "LOW"
           WHEN SIZE_OF_COLONY BETWEEN 101 AND 1000 THEN "MEDIUM"
           WHEN SIZE_OF_COLONY > 1000 THEN "HIGH" END as SIZE
FROM ECOLI_DATA 
ORDER BY 1



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

문제
FISH_INFO에서 평균 길이가 33cm 이상인 물고기들을 종류별로 분류하여 잡은 수, 최대 길이, 물고기의 종류를 출력하는 SQL문을 작성해주세요. 결과는 물고기 종류에 대해 오름차순으로 정렬해주시고, 10cm이하의 물고기들은 10cm로 취급하여 평균 길이를 구해주세요.
컬럼명은 물고기의 종류 'FISH_TYPE', 잡은 수 'FISH_COUNT', 최대 길이 'MAX_LENGTH'로 해주세요.

SELECT COUNT(ID) as FISH_COUNT
        , MAX(ifnull(LENGTH,10)) as MAX_LENGTH
        , FISH_TYPE
FROM FISH_INFO 
WHERE FISH_TYPE IN (
                    SELECT FISH_TYPE
                    FROM FISH_INFO
                    GROUP BY FISH_TYPE
                    HAVING AVG(ifnull(LENGTH,10)) >= 33
                    )
GROUP BY FISH_TYPE
ORDER BY FISH_TYPE



- 물고기 종류 별 대어 찾기

문제
물고기 종류 별로 가장 큰 물고기의 ID, 물고기 이름, 길이를 출력하는 SQL 문을 작성해주세요.

물고기의 ID 컬럼명은 ID, 이름 컬럼명은 FISH_NAME, 길이 컬럼명은 LENGTH로 해주세요.
결과는 물고기의 ID에 대해 오름차순 정렬해주세요.
단, 물고기 종류별 가장 큰 물고기는 1마리만 있으며 10cm 이하의 물고기가 가장 큰 경우는 없습니다.

with max_length as
(
    SELECT fish_type, max(ifnull(length,0)) as len
    FROM FISH_INFO
    GROUP BY 1
)

SELECT id, fish_name, length
FROM FISH_INFO as fi 
    LEFT OUTER JOIN  max_length as ml
    ON fi.fish_type = ml.fish_type
    LEFT OUTER JOIN FISH_NAME_INFO as fni
    ON fi.fish_type = fni.fish_type 
WHERE fi.length = ml.len
ORDER BY 1





[4월 23일]

- 부서별 평균 연봉 조회하기

문제
HR_DEPARTMENT와 HR_EMPLOYEES 테이블을 이용해 부서별 평균 연봉을 조회하려 합니다.
부서별로 부서 ID, 영문 부서명, 평균 연봉을 조회하는 SQL문을 작성해주세요.
평균연봉은 소수점 첫째 자리에서 반올림하고 컬럼명은 AVG_SAL로 해주세요.
결과는 부서별 평균 연봉을 기준으로 내림차순 정렬해주세요.

SELECT he.DEPT_ID
    , DEPT_NAME_EN
    , ROUND(AVG(SAL),0) as AVG_SAL
FROM HR_EMPLOYEES  as he
    LEFT OUTER JOIN HR_DEPARTMENT as hd
    ON he.DEPT_ID = hd.DEPT_ID
GROUP BY 1,2
ORDER BY 3 DESC



- 조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기

문제
USED_GOODS_BOARDUSED_GOODS_FILE 테이블에서 조회수가 가장 높은 중고거래 게시물에 대한 첨부파일 경로를 조회하는 SQL문을 작성해주세요.
첨부파일 경로는 FILE ID를 기준으로 내림차순 정렬해주세요.
기본적인 파일경로는 /home/grep/src/ 이며, 게시글 ID를 기준으로 디렉토리가 구분되고, 파일이름은 파일 ID, 파일 이름, 파일 확장자로 구성되도록 출력해주세요.
조회수가 가장 높은 게시물은 하나만 존재합니다.

SELECT CONCAT("/home/grep/src/",ugf.BOARD_ID,"/",FILE_ID,FILE_NAME,FILE_EXT) as FILE_PATH
FROM USED_GOODS_FILE as ugf
    JOIN (SELECT BOARD_ID, VIEWS
            FROM USED_GOODS_BOARD 
            ORDER BY VIEWS DESC
            LIMIT 1) as ugb
    ON ugb.BOARD_ID = ugf.BOARD_ID
ORDER BY FILE_ID DESC

⬇️ 얼마전 window funtion을 배워서 다시 풀어 보았다. ⬇️

WITH path as (

SELECT rank() over (order by VIEWS desc) as view_rank
        ,CONCAT("/home/grep/src/",ugf.BOARD_ID, "/" , ugf.FILE_ID, ugf.FILE_NAME, ugf.FILE_EXT ) as FILE_PATH
FROM USED_GOODS_BOARD as ugb
    LEFT OUTER JOIN USED_GOODS_FILE as ugf
    ON ugb.BOARD_ID = ugf.BOARD_ID
    
    
    )
    
SELECT FILE_PATH
FROM path
WHERE view_rank = 1



- 조건에 맞는 사용자 정보 조회하기

문제
USED_GOODS_BOARDUSED_GOODS_USER 테이블에서 중고 거래 게시물을 3건 이상 등록한 사용자의
사용자 ID, 닉네임, 전체주소, 전화번호를 조회하는 SQL문을 작성해주세요.
이때, 전체 주소는 시, 도로명 주소, 상세 주소가 함께 출력되도록 해주시고,
전화번호의 경우 xxx-xxxx-xxxx 같은 형태로 하이픈 문자열(-)을 삽입하여 출력해주세요.
결과는 회원 ID를 기준으로 내림차순 정렬해주세요.

SELECT USER_ID
        , NICKNAME
        , CONCAT(CITY," ",STREET_ADDRESS1," ",STREET_ADDRESS2) as "전체주소"
        , CONCAT(LEFT(TLNO,3),"-",SUBSTR(TLNO,4,4),"-",RIGHT(TLNO,4)) as "전화번호"
FROM USED_GOODS_USER as ugu
        JOIN USED_GOODS_BOARD as ugb
        ON ugu.USER_ID = ugb.WRITER_ID
GROUP BY USER_ID
HAVING COUNT(DISTINCT BOARD_ID) >= 3
ORDER BY USER_ID DESC



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

문제
USED_GOODS_BOARDUSED_GOODS_USER 테이블에서
완료된 중고 거래의 총금액이 70만 원 이상인 사람의
회원 ID, 닉네임, 총거래금액을 조회하는 SQL문을 작성해주세요.
결과는 총거래금액을 기준으로 오름차순 정렬해주세요.


SELECT USER_ID
    ,NICKNAME
    ,SUM(PRICE) as TOTAL_SALES
FROM USED_GOODS_BOARD as ugb
    LEFT OUTER JOIN USED_GOODS_USER as ugu
    ON ugb.WRITER_ID = ugu.USER_ID
WHERE STATUS = "DONE" 
GROUP BY 1,2
HAVING SUM(PRICE) >= 700000
ORDER BY 3 





[4월 24일]

- 대여 기록이 존재하는 자동차 리스트 구하기

문제
CAR_RENTAL_COMPANY_CAR 테이블과 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 자동차 종류가 '세단'인 자동차들 중
10월에 대여를 시작한 기록이 있는 자동차 ID 리스트를 출력하는 SQL문을 작성해주세요.
자동차 ID 리스트는 중복이 없어야 하며, 자동차 ID를 기준으로 내림차순 정렬해주세요.

SELECT DISTINCT c.CAR_ID
FROM CAR_RENTAL_COMPANY_CAR as c
    JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY  as rh
    ON c.CAR_ID = rh.CAR_ID
WHERE c.CAR_TYPE = "세단"
    AND rh.START_DATE BETWEEN "2022-10-01" AND "2022-10-31"
ORDER BY 1 DESC



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

문제
CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 2022년 10월 16일에 대여 중인 자동차인 경우 '대여중' 이라고 표시하고,
대여 중이지 않은 자동차인 경우 '대여 가능'을 표시하는 컬럼(컬럼명: AVAILABILITY)을 추가하여
자동차 ID와 AVAILABILITY 리스트를 출력하는 SQL문을 작성해주세요.
이때 반납 날짜가 2022년 10월 16일인 경우에도 '대여중'으로 표시해주시고 결과는 자동차 ID를 기준으로 내림차순 정렬해주세요.

SELECT CAR_ID,
    MAX(CASE WHEN '2022-10-16' 
        BETWEEN DATE_FORMAT(START_DATE, '%Y-%m-%d') AND DATE_FORMAT(END_DATE, '%Y-%m-%d') 
        THEN '대여중' ELSE '대여 가능'END) AS AVAILABILITY 
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY 
GROUP BY CAR_ID
ORDER BY CAR_ID DESC

항상 컬럼 between 날짜 and 날짜로 사용했는데
날짜 between 컬럼 and 컬럼이라 색달랐다.



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

문제
CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 대여 시작일을 기준으로
2022년 8월부터 2022년 10월까지 총 대여 횟수가 5회 이상인 자동차들에 대해서
해당 기간 동안의 월별 자동차 ID 별 총 대여 횟수(컬럼명: RECORDS) 리스트를 출력하는 SQL문을 작성해주세요.
결과는 월을 기준으로 오름차순 정렬하고, 월이 같다면 자동차 ID를 기준으로 내림차순 정렬해주세요.
특정 월의 총 대여 횟수가 0인 경우에는 결과에서 제외해주세요.

SELECT MONTH(START_DATE) as MONTH
    , CAR_ID
    , COUNT(HISTORY_ID) as RECORDS
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY 
WHERE (CAR_ID IN (
                SELECT CAR_ID
                FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
                WHERE DATE_FORMAT(START_DATE,"%Y-%m") BETWEEN "2022-08" AND "2022-10"
                GROUP BY CAR_ID
                HAVING COUNT(CAR_ID) >= 5
                ) )
     AND DATE_FORMAT(START_DATE,"%Y-%m") BETWEEN "2022-08" AND "2022-10"
GROUP BY 1,2
HAVING COUNT(HISTORY_ID) > 0
ORDER BY 1, 2 DESC

처음 풀이는 where절 서브쿼리를 메인쿼리로 사용하고
특정월의 총 대여횟수가 0인 경우를 서브쿼리로 넣어서 풀이하였으나,
출력물이 월별으로 나와야 했기 때문에 전체기간 동안의 대여횟수 5회 조건이 특정월의 대여횟수 5회가 되어버려서
잘못된 쿼리를 작성했다.
서브쿼리에 어떤 조건을 넣을 지 먼저 고민해봐야 할것 같다.



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

문제
2022년 1월의 카테고리 별 도서 판매량을 합산하고, 카테고리(CATEGORY), 총 판매량(TOTAL_SALES) 리스트를 출력하는 SQL문을 작성해주세요.
결과는 카테고리명을 기준으로 오름차순 정렬해주세요.

SELECT CATEGORY, SUM(SALES) as TOTAL_SALES
FROM BOOK_SALES as bs
    LEFT OUTER JOIN BOOK as b
    ON bs.BOOK_ID = b.BOOK_ID
WHERE DATE_FORMAT(SALES_DATE,"%Y-%m") = "2022-01"
GROUP BY 1
ORDER BY 1



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

문제
REST_INFO 테이블에서 음식종류별로 즐겨찾기수가 가장 많은 식당의 음식 종류, ID, 식당 이름, 즐겨찾기수를 조회하는 SQL문을 작성해주세요.
이때 결과는 음식 종류를 기준으로 내림차순 정렬해주세요


SELECT ri.FOOD_TYPE, REST_ID, REST_NAME, ri.FAVORITES
FROM REST_INFO as ri
                JOIN (
                    SELECT FOOD_TYPE, MAX(FAVORITES) as FAVORITES
                    FROM REST_INFO 
                    GROUP BY FOOD_TYPE
                    ) as mf
                ON ri.FOOD_TYPE = mf.FOOD_TYPE AND ri.FAVORITES = mf.FAVORITES 
ORDER BY 1 DESC

group by 시 가장 여러운 유형이 group by 1개에 집계함수가 오지만 그 조건에 따른 다른 컬럼이 와야할 때 인것같다.
group by는 food_type 하나만 와야 하지만
컬럼은 max(FAVORITES)에 맞는 REST_ID, REST_NAME를 불러와야하기 때문에
join on에 2개를 붙혀서 풀었다.





[4월 25일]

- 조건별로 분류하여 주문상태 출력하기

문제
FOOD_ORDER 테이블에서 5월 1일을 기준으로 주문 ID, 제품 ID, 출고일자, 출고여부를 조회하는 SQL문을 작성해주세요. 출고여부는 5월 1일까지 출고완료로 이 후 날짜는 출고 대기로 미정이면 출고미정으로 출력해주시고, 결과는 주문 ID를 기준으로 오름차순 정렬해주세요.

SELECT ORDER_ID
    , PRODUCT_ID
    , DATE_FORMAT(OUT_DATE, "%Y-%m-%d") as OUT_DATE
    , CASE WHEN OUT_DATE <= "2022-05-01" THEN "출고완료"
           WHEN OUT_DATE > "2022-05-01" THEN "출고대기"
           WHEN OUT_DATE is null THEN "출고미정" END as 출고여부
FROM FOOD_ORDER 
ORDER BY 1



- 헤비 유저가 소유한 장소

문제
이 서비스에서는 공간을 둘 이상 등록한 사람을 "헤비 유저"라고 부릅니다. 헤비 유저가 등록한 공간의 정보를 아이디 순으로 조회하는 SQL문을 작성해주세요.

SELECT *
FROM PLACES
WHERE HOST_ID IN ( SELECT HOST_ID
                    FROM PLACES 
                    GROUP BY HOST_ID
                    HAVING COUNT(HOST_ID) > 1
                    )
ORDER BY ID



- 오랜 기간 보호한 동물(1)

문제
아직 입양을 못 간 동물 중, 가장 오래 보호소에 있었던 동물 3마리의 이름과 보호 시작일을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 시작일 순으로 조회해야 합니다.

SELECT ai.NAME, ai.DATETIME
FROM ANIMAL_INS as ai 
    LEFT OUTER JOIN ANIMAL_OUTS as ao
    ON ai.ANIMAL_ID = ao.ANIMAL_ID
WHERE ao.DATETIME is null
ORDER BY 2
LIMIT 3

⬇️ 얼마전 window funtion을 배워서 다시 풀어 보았다. ⬇️

WITH info as
            (SELECT ai.NAME
                , ai.DATETIME
                , rank() over (order by ai.DATETIME) as start_rank
            FROM ANIMAL_INS as ai 
                LEFT OUTER JOIN ANIMAL_OUTS as ao
                ON ai.ANIMAL_ID = ao.ANIMAL_ID
            WHERE ao.DATETIME is null)

SELECT name, datetime
from info
where start_rank <= 3



- 오랜 기간 보호한 동물(2)

문제
입양을 간 동물 중, 보호 기간이 가장 길었던 동물 두 마리의 아이디와 이름을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 기간이 긴 순으로 조회해야 합니다.


WITH a as (
SELECT ao.ANIMAL_ID, ao.NAME,(ao.DATETIME - ai.DATETIME) as diff
FROM ANIMAL_OUTS as ao
    LEFT OUTER JOIN ANIMAL_INS as ai
    ON ao.ANIMAL_ID = ai.ANIMAL_ID )
    
SELECT ANIMAL_ID, NAME
FROM a
ORDER BY diff DESC
LIMIT 2

⬇️ 얼마전 window funtion을 배워서 다시 풀어 보았다. ⬇️

WITH df as (
            SELECT ao.ANIMAL_ID, ao.NAME
                    ,rank() over (order by (ao.DATETIME- ai.DATETIME) desc) as period
            FROM ANIMAL_OUTS as ao
                    LEFT OUTER JOIN ANIMAL_INS as ai
                    ON ao.ANIMAL_ID = ai.ANIMAL_ID
            )

SELECT ANIMAL_ID, NAME
FROM df
WHERE period <= 2



- 있었는데요 없었습니다

문제
관리자의 실수로 일부 동물의 입양일이 잘못 입력되었습니다. 보호 시작일보다 입양일이 더 빠른 동물의 아이디와 이름을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 시작일이 빠른 순으로 조회해야합니다.

SELECT ao.ANIMAL_ID, ao.NAME
FROM ANIMAL_OUTS as ao
    JOIN ANIMAL_INS as ai
    ON ao.ANIMAL_ID = ai.ANIMAL_ID
WHERE ao.DATETIME < ai.DATETIME
ORDER BY ai.DATETIME





[4월 26일]

- 없어진 기록 찾기

문제
천재지변으로 인해 일부 데이터가 유실되었습니다. (ㅋㅋ)
입양을 간 기록은 있는데, 보호소에 들어온 기록이 없는 동물의 ID와 이름을 ID 순으로 조회하는 SQL문을 작성해주세요.

SELECT ao.ANIMAL_ID, ao.NAME
FROM ANIMAL_OUTS as ao
    LEFT OUTER JOIN ANIMAL_INS as ai
    ON ao.ANIMAL_ID = ai.ANIMAL_ID
WHERE ai.DATETIME is null
ORDER BY 1



- 업그레이드 할 수 없는 아이템 구하기 🌟

문제
더 이상 업그레이드할 수 없는 아이템의 아이템 ID(ITEM_ID), 아이템 명(ITEM_NAME), 아이템의 희귀도(RARITY)를 출력하는 SQL 문을 작성해 주세요. 이때 결과는 아이템 ID를 기준으로 내림차순 정렬해 주세요.

SELECT ITEM_ID, ITEM_NAME, RARITY
FROM ITEM_INFO 
WHERE ITEM_ID not in (
                    SELECT PARENT_ITEM_ID
                    FROM ITEM_TREE
                    WHERE PARENT_ITEM_ID is not null)
ORDER BY 1 DESC

문제 이해가 조금 어려웠다.
결국에는 PARENT_ITEM_ID애 언급되지 않는 아이템을 구하는 문제



- 대장균의 크기에 따라 분류하기 2

문제
대장균 개체의 크기를 내름차순으로 정렬했을 때 상위 0% ~ 25% 를 'CRITICAL', 26% ~ 50% 를 'HIGH', 51% ~ 75% 를 'MEDIUM', 76% ~ 100% 를 'LOW' 라고 분류합니다. 대장균 개체의 ID(ID) 와 분류된 이름(COLONY_NAME)을 출력하는 SQL 문을 작성해주세요. 이때 결과는 개체의 ID 에 대해 오름차순 정렬해주세요 . 단, 총 데이터의 수는 4의 배수이며 같은 사이즈의 대장균 개체가 서로 다른 이름으로 분류되는 경우는 없습니다.

SELECT ID
    , CASE WHEN ntile(4) over (order by SIZE_OF_COLONY desc) = 1 THEN "CRITICAL"
           WHEN ntile(4) over (order by SIZE_OF_COLONY desc) = 2 THEN "HIGH"
           WHEN ntile(4) over (order by SIZE_OF_COLONY desc) = 3 THEN "MEDIUM"
           WHEN ntile(4) over (order by SIZE_OF_COLONY desc) = 4 THEN "LOW"
           END as COLONY_NAME
FROM ECOLI_DATA 
ORDER BY 1

ntile함수를 알게 된 문제였다 !
참고링크 : https://goldswan.tistory.com/25






Study Note
profile
Study Log

0개의 댓글