SQL 코테 대비

sckwon770·2023년 10월 18일

코딩테스트

목록 보기
1/2

계속 업데이트 할 예정

_

문법 점검


-- 조건
CASE WHEN ~ THEN ~
	 WHEN ~ THEN ~
     ELSE ~
END

--- NULL은 = 연산자 안됨
WHERE age IS NULL
WHERE age IS NOT NULL

_

SELECT


동일한 고객이 동일한 상품을 재구매한 경우 출력

GROUP BY HAVING

  • WHERE GROUP BY랑 헷갈리면 안됨 (에러)
SELECT user_id, product_id
FROM online_sale
GROUP BY user_id, product_id
HAVING COUNT(*) >= 2
ORDER BY user_id ASC, product_id desc

_

JOIN


친구의 봉급이 더 큰 사람의 이름을 친구 봉급으로 정렬

SELECT s1.name
FROM friends f1
JOIN packages p1 ON f1.id = p1.id
JOIN friends f2 ON f1.friend_id = f2.id
JOIN packages p2 on f2.id = p2.id
join students s1 on f1.id = s1.id
WHERE p1.salary < p2.salary
ORDER BY p2.salary
SELECT s.name
FROM students s
    JOIN (friends f, packages ps, packages pf)
    ON s.id = f.id
    AND s.id = ps.id
    AND f.friend_id = pf.id
WHERE ps.salary < pf.salary
ORDER BY pf.salary

상반기와 7월 아이스크림 출하량의 합이 큰 3개 출력

  • FIRST_HALF (FLAVOR PK, SHIPMENT_ID FK)

  • JULY (SHIPMENT_ID PK, FLAVOR FK)

  • 7월에 주문량 폭주로 동일한 맛 아이스크림이 여러 번 출하됐다.

LEFT JOIN, GROUP BY

  • 두 테이블에 걸쳐서 출하량의 합을 구해야 함
    • 한 테이블로 JOIN하고 계산으로 정렬
    • JULY는 중복 출하가 있었지만, FIRST_HALF에 없는 FLAVOR가 있을 수 없으므로 FK로서 LEFT JOIN
      • 중복 데이터 때문에 여러 ROW 발생
      • f.total_order + SUM(j.total_order) f.total_order까지 SUM하면 중복 ROW 때문에 값 뻥튀기

복잡한 JOIN

https://school.programmers.co.kr/learn/courses/30/lessons/157339

SELECT a.car_id, a.car_type, 
       ROUND(
           a.daily_fee * 30 * (1 - (p.discount_rate / 100)),
           0
       ) AS FEE
FROM car_rental_company_car a
LEFT JOIN car_rental_company_discount_plan p
ON a.car_type = p.car_type
WHERE
    a.car_type IN ('세단', 'SUV') AND
    p.duration_type = '30일 이상' AND
    a.daily_fee * 30 * (1 - (p.discount_rate / 100)) BETWEEN 500000 AND 2000000 AND
    a.car_id NOT IN (
        SELECT car_id
        FROM car_rental_company_rental_history
        WHERE '2022-11-01' <= end_date AND start_date < '2022-12-01'
    )
ORDER BY FEE DESC, a.car_type, a.car_id DESC

_

문자열


모음(a,e,i,o,u)로 끝나는 이름들 출력

LIKE 이용

  • %: 모든 문자
  • _: 한 글자
select distinct(city) from station where city LIKE "%a" or city LIKE "%e" or city LIKE "%i" or city LIKE "%o" or city LIKE "%u"

REGEXP 이용

select distinct(city) from station where city REGEXP ('a$|e$|i$|o$|u$')
select distinct(city) from station where city REGEXP '[aeiou]$'

모음(a,e,i,o,u)로 시작하고 끝나는 이름들 출력

REGEXP AND

select distinct(city) from station where city REGEXP '^[aeiou]' and city REGEXP '[aeiou]$'

REGEXP +

  • .: any character
  • *: 일반 LIKE 쓰듯이 쓰면 안됨. 앞에 Matching pattern 필요.
select distinct(city) from station where city REGEXP '^[aeiou].*[aeiou]$'

반례

  • | 는 OR 이므로, 이렇게 할 수 없음
select distinct(city) from station where city REGEXP '^[aeiou]|[aeiou]$'
  • 이름 사이에 공백이 있는 경우, 문제 발생
select distinct(city) from station where city REGEXP '^[aeiou][A-z]*[aeiou]$'

모음(a,e,i,o,u)로 시작하지 않는 이름들 출력

REGEXP NOT

select distinct(city) from station where city REGEXP '^[^aeiou]'

_

숫자


소수점 5자리에서 | 소수점 4자리까지 | to a scale of 4 decimal places

SELECT round(13.12345, 4); -- 숫자 없으면, 정수로
SELECT truncate(13.12345, 4); -- 숫자 아래로 삭제 (floor)

SELECT floor(13.12345); -- 정수로만 가능
SELECT ceil(13.12345); -- 정수로만 가능

_

날짜


WHERE date1 BETWEEN '2022-09-01' and '2022-09-26' -- 0시 기준이므로 26일 비포함
WHERE date1 BETWEEN '2022-09-01 00:00:00' and '2022-09-26 23:59:59'

DATEDIFF(date1, date2) 
DATE_ADD(date1, INTERVAL 100 DAY); -- SECOND,MINUTE,HOUR
DATE_ADD(date1, INTERVAL 1 MONTH); -- DAY,MONTH,YEAR

_

문자


날짜 포멧팅

DATE_FORMAT(날짜, 형식)
기호역할기호역할
%Y4자리 연도%y2자리 연도
%m두자리 숫자 월%c한자리 숫자 월
%M긴 영어 월%b짧은 영어 월
%d두자리 일%e한자리 일
%W긴 영어 요일%a짧은 영어 요일
%I12시간제 시%H24시간제 시
%i%S
%Thh:mm:ss%rhh:mm:ss AM/PM
%pAM/PM

참고자료

https://www.techonthenet.com/mysql/index.php

profile
늘 학습하고 적용하고 개선하는 개발자

0개의 댓글