241024_TIL

J Lee·2024년 10월 24일
0

아무리 사소하더라도 배움이 없는 날은 없다.

SQL 문제풀이 복습


Leetcode

문제 링크
기본적인 window함수 문제.
rank()는 공동 등수가 발생할 경우 다음 등수를 건너뛴다.
(1등이 2명일 경우 다음 값은 3이 됨)

dense_rank()는 공동 등수가 발생하더라도 다음 등수를 건너뛰지 않는다.
(1등이 2명이더라도 다음 값이 2가 됨)

SELECT score,
       Dense_rank()
         OVER(
           ORDER BY score DESC) AS "rank"
FROM   Scores
ORDER  BY 1 DESC;

문제 링크
union + join + count

SELECT a.player_id,
       p.player_name,
       Count(*) AS "grand_slams_count"
FROM   (SELECT Wimbledon AS "player_id"
        FROM   Championships
        UNION ALL
        SELECT Fr_open
        FROM   Championships
        UNION ALL
        SELECT US_open
        FROM   Championships
        UNION ALL
        SELECT Au_open
        FROM   Championships) a
       JOIN Players p
         ON a.player_id = p.player_id
GROUP  BY 1;

문제 링크
1트(5/8)와 2트(6/21) 때의 풀이가 같았어서
오늘은 일부러 다르게 풀어서 해결했다.

즉, primary_flag = Y인 employee를 구하는 쿼리와
primary_flag = N이면서 숫자가 하나밖에 없는 쿼리를 각각 짜서
union하는 방식이 아니라,
window 함수를 써서 row_id를 만들되
order by의 조건을 employee_id와 primary_flag 기준으로 오름차순하도록 하는 것.
이렇게 한 다음 결과를 인라인뷰로 저장하고 row_id가 1인 것만 불러오면 된다.

이 방식대로 하면 primary_flag가 뭐든간에
있는 놈은 있는대로 불러오고 없는 놈은 자동으로 현재 소속부서가 불러와지게 됨.

SELECT employee_id,
       department_id
FROM   (SELECT employee_id,
               department_id,
               primary_flag,
               Rank()
                 OVER(
                   partition BY employee_id
                   ORDER BY employee_id, primary_flag) AS "row_id"
        FROM   Employee) a
WHERE  row_id = '1';

프로그래머스

문제 링크
찾아보니 본격적인 부트캠프가 시작하기도 전인
4월 초에 처음 풀었었던 문제였다.
그 때는 이게 왜 그렇게 어려웠던 걸까ㅠ 허허..

SELECT DISTINCT h.CAR_ID,
                CASE
                  WHEN rented IS NULL THEN '대여 가능'
                  WHEN rented IS NOT NULL THEN '대여중'
                end AS "AVAILABILITY"
FROM   CAR_RENTAL_COMPANY_RENTAL_HISTORY h
       LEFT JOIN (SELECT car_id AS "rented"
                  FROM   CAR_RENTAL_COMPANY_RENTAL_HISTORY
                  WHERE  '2022-10-16' BETWEEN START_DATE AND END_DATE) a
              ON h.CAR_ID = a.rented
ORDER  BY 1 DESC;

문제 링크
으으 치사해
어렵지도 않은데 괜히 조건만 복잡하게 꼬아서 내는 이런 문제 진짜 별로;

SELECT c.CAR_ID,
       c.CAR_TYPE,
       Round(daily_fee * 30 * ( 1 - ( DISCOUNT_RATE / 100 ) )) AS "FEE"
FROM   CAR_RENTAL_COMPANY_CAR c
       JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY h
         ON c.CAR_ID = h.CAR_ID
            AND c.CAR_TYPE IN ( '세단', 'SUV' )
       JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN d
         ON c.CAR_TYPE = d.CAR_TYPE
            AND d.DURATION_TYPE = '30일 이상'
WHERE  c.CAR_ID NOT IN (SELECT CAR_ID
                        FROM   CAR_RENTAL_COMPANY_RENTAL_HISTORY
                        WHERE  ( '2022-11-01 00:00:00' BETWEEN
                                 START_DATE AND END_DATE
                               )
                                OR ( '2022-11-30 23:59:59' BETWEEN
                                     START_DATE AND END_DATE ))
GROUP  BY 1
HAVING FEE >= 500000
       AND FEE < 2000000
ORDER  BY 3 DESC,
          2 ASC,
          1 DESC;

문제 링크
이것도 join의 조건이 괜히 복잡하게 생겨서 그렇지
그것만 놓치지 않고 잘 주면 별 건 없다.
join의 조건을 줄 때도 case when을 쓸 수 있다, 정도만 기억하면 될 듯.
굳이 하나를 더 꼽자면 연산을 할 때도 case when을 쓰는 방법 정도?

SELECT HISTORY_ID,
       Round(DAILY_FEE * ( Datediff(END_DATE, START_DATE) + 1 ) *
             ( 1 - ( CASE
                       WHEN
                   discount_rate IS NULL THEN 0
                                                                            ELSE
                   discount_rate / 100
                                                                          end )
             )
       ) AS
       "FEE"
FROM   CAR_RENTAL_COMPANY_CAR c
       JOIN CAR_RENTAL_COMPANY_RENTAL_HISTORY h
         ON c.CAR_ID = h.CAR_ID
            AND c.CAR_TYPE = '트럭'
       LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN d
              ON c.CAR_TYPE = d.CAR_TYPE
                 AND CASE
                       WHEN Datediff(END_DATE, START_DATE) + 1 >= 90 THEN
                       '90일 이상'
                       WHEN Datediff(END_DATE, START_DATE) + 1 >= 30 THEN
                       '30일 이상'
                       WHEN Datediff(END_DATE, START_DATE) + 1 >= 7 THEN
                       '7일 이상'
                     end = d.DURATION_TYPE
ORDER  BY 2 DESC,
          1 DESC;

문제 링크
where절 안에 서브쿼리를 넣어서
기준 시점 동안 5회 이상 렌트된 이력이 있는 car_id만 뽑는 것이 키.
그거 외엔 딱히 어려울 거 없음.

SELECT Month(START_DATE) AS "MONTH",
       h.CAR_ID,
       Count(*)          AS "RECORDS"
FROM   CAR_RENTAL_COMPANY_RENTAL_HISTORY h
WHERE  START_DATE BETWEEN '2022-08-01' AND '2022-10-31'
       AND CAR_ID IN (SELECT car_id
                      FROM   CAR_RENTAL_COMPANY_RENTAL_HISTORY
                      WHERE  START_DATE BETWEEN '2022-08-01' AND '2022-10-31'
                      GROUP  BY 1
                      HAVING Count(*) >= 5)
GROUP  BY 1,
          2
ORDER  BY 1,
          2 DESC;

문제 링크
case when, date_format, where.. 기냥기냥 무난한 문제

SELECT HISTORY_ID,
       CAR_ID,
       Date_format(START_DATE, '%Y-%m-%d') AS "START_DATE",
       Date_format(END_DATE, '%Y-%m-%d')   AS "END_DATE",
       CASE
         WHEN Datediff(END_DATE, START_DATE) + 1 >= 30 THEN '장기 대여'
         ELSE '단기 대여'
       end                                 AS "RENT_TYPE"
FROM   CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE  START_DATE BETWEEN '2022-09-01' AND '2022-09-30'
ORDER  BY 1 DESC;
profile
기본기를 소홀히 하지 말자

0개의 댓글

관련 채용 정보