SQL/DataBase
[SQL] 59042 없어진 기록 찾기
프로그래머스 [SQL] 없어진 기록 찾기
❌ 오답
SELECT o.animal_id, o.name
FROM animal_ins i RIGHT OUTER JOIN animal_outs o ON i.animal_id = o.animal_id
WHERE o.animal_id is not null AND i.animal_id is null;
ORDER BY o.animal_id;
✅ o.animal_id IS NOT NULL ← 불필요한 조건
- animal_outs o는 RIGHT OUTER JOIN에서 기준 테이블이므로 절대 NULL이 될 수 없다.
- 따라서 이 조건은 쓸 필요가 없다.
✅ RIGHT OUTER JOIN 사용 ← 동일 결과지만 덜 직관적
- 일반적으로 OUTER JOIN 할 때는 기준 테이블을 왼쪽에 놓는다.
- LEFT OUTER JOIN을 사용하는 것이 권장되기 때문이다.
- RIGHT OUTER JOIN은 해석이 어렵고 비추천되는 방식이라고 한다.
정답 코드
SELECT o.animal_id, o.name
FROM animal_outs o LEFT OUTER JOIN animal_ins i ON o.animal_id = i.animal_id
WHERE i.animal_id is null
ORDER BY o.animal_id;
🚗 [SQL] 151138 자동차 대여 기록에서 장기/단기 대여 구분하기
프로그래머스 [SQL] 자동차 대여 기록에서 장기/단기 대여 구분하기
- https://school.programmers.co.kr/learn/courses/30/lessons/151138
1. 문제
car_rental_company_car
,car_rental_company_rental_history
,car_rental_company_discount_plan
테이블 제공- '세단', 'SUV' 차종 중 2022년 11월 한 달 간 대여 가능한 차량을 찾고, 30일 요금 기준 정렬
2. 실패한 시도
❌ 오답
SELECT j.car_id, j.car_type, j.daily_fee * ((100 - j.discount_rate)*0.01) * 30 AS fee
FROM (car_rental_company_car c INNER JOIN car_rental_company_discount_plan d ON c.car_type = d.car_type) AS j
INNER JOIN car_rental_company_rental_history h ON j.car_id = h.car_id
WHERE car_type = '세단' OR 'SUV' AND h.end_date < '2024-11-01'
ORDER BY fee DESC, j.car_type, j.car_id DESC
✅ SQL WHERE 절에서 논리 오류 주의
'SUV'
단독은 항상 true 로 인식된다. 이렇게 하면 모든 car_type이 포함된다.- →
IN ('세단', 'SUV')
사용해야 정확하다.
✅ 날짜 조건을 부정확하게 작성함
- 날짜 범위 필터링시 NOT EXISTS 사용한다.
- 겹치는 날짜 조건을 부정해서 제외할 차량을 정의해야 함
- 기간 겹침 확인은
NOT (end < 시작 OR start > 종료)
로 부정
✅ GROUP BY는 중복 방지용이 아니다.
- 문제에서 요구하지 않는 이상, JOIN 결과 중복 발생 원인을 먼저 점검할 것
✅ ROUND 함수로 실수처리한다.
- 계산식 결과는 실수이다. →
ROUND()
로 정수 변환이 필요하다.
3. 정답 코드
SELECT j.car_id, j.car_type, ROUND(j.daily_fee * ((100 - j.discount_rate)*0.01) * 30) AS fee
FROM (
SELECT c.car_id, c.car_type, c.daily_fee, d.discount_rate
FROM car_rental_company_car c
INNER JOIN car_rental_company_discount_plan d
ON c.car_type = d.car_type AND d.duration_type = '30일 이상') AS j
WHERE car_type IN ('세단', 'SUV')
AND NOT EXISTS (
SELECT 1
FROM car_rental_company_rental_history h2
WHERE h2.car_id = j.car_id
AND NOT (h2.end_date < '2022-11-01' OR h2.start_date > '2022-11-30')
)
ORDER BY fee DESC, j.car_type, j.car_id DESC;
- NOT EXISTS 절에서 "11월 한 달이라도 대여된 차는 제외"
- 날짜 범위:
NOT (end < 11월 1일 OR start > 11월 30일)
→ 겹치는 대여기간 필터링 - 할인 조건:
duration_type = '30일 이상'
- 요금:
ROUND()
함수로 정수 처리
📌 TMI:
- 복잡한 SQL일수록 점진적으로 테스트하면서 WHERE절 조건을 명확히 파악해야 함.