안녕하세요, SQL 실력향상을 위해 인터넷에 떠돌아다니는 문제를 풀어보고 있습니다.
도저히 모르겠는 SQL문이 있는데, 힌트만 주신다면 다시 검색해서 다시 풀어보고 싶습니다.
문제는 아래와 같습니다.
우선, RESERVATION 테이블이 주어집니다.
```sql
CREATE TABLE `reservation`
( `id` int comment '예약 ID',
`user_id` int comment '유저 ID',
`start_time` datetime comment '회의실 시작 시간',
`end_time` datetime comment '회의실 종료 시간'
);
```
테이블은 위와 같고,
데이터는 첨부파일(질문_사진첨부_01.jpg) 이고, 문제는 아래와 같습니다.
- ID가 1인 요청은 가장 빠른 요청이므로 예약이 확정됩니다.
- ID가 2인 요청은 ID가 1인 요청과 시간이 겹치지 않기 때문에 예약이 확정됩니다. 종료 시각과 시작 시각이 같다면 서로 겹치지 않습니다.
- ID가 3인 요청은 ID가 2인 요청과 시간이 겹치기 때문에 예약이 취소됩니다.
이런식으로 시간이 겹치면 안되고 결과는 아이디가 1,2,5만 나와야합니다.
나름 SQL문에 자신있었는데, 감을 못잡겠습니다. 재귀함수를 이용해야 하는건지, 셀프조인으로 뭔가 계속 해결해야 하는건지, 간단한 방법이 있는지
정말 궁금합니다.
답변주시면 감사하겠습니다.
OSS! ?
와.. 6시간 고민 끝에 풀었습니다.
select
r.id,
r.start_time,
r.end_time
from reservation as r
left join
(
select
id+1 as t_id ,
start_time as t_start,
end_time as t_end
from reservation) as t_reservation
on r.id = t_reservation.t_id
where r.id = 1 or t_reservation.t_end <= r.start_time
헉 근데, 결과는 맞췄는데, 최종 정답은 틀렸네요....더 좋은 방법이 있을까요?
푸신 방법은 바로 직전 id 하나만 비교합니다.
시간 비교도 너무 단순하구요.
순차적으로 직전 모든 id 와 복합적으로 비교해야 하므로 오답입니다.
간단한 예로 1번 id 가 1월1일부터 31일까지 예약했다면?
나머지 모든 id 는 예약 불가입니다.
조금 더 복잡한 예를 들어보면
1번이 13시 ~ 15시
2번이 14시 ~ 16시
3번이 15시 ~ 17시
이렇게 같은 날 예약을 신청했다면?
1번 예약 확정
2번은 1번과 시간이 겹치므로 예약 취소
3번은 2번과 시간이 겹치지만 2번이 취소되었고 1번과는 겹치지 않으니 예약 확정
절차적 처리가 필요한 요구사항으로 SQL 만으로는 쉽지 않은 문제입니다.
재귀쿼리를 이용한 풀이가 가능할지는
다양한 시행착오를 통한 고민이 필요할 것 같습니다.
답변감사합니다 마농님
해당 문제는 SQL 만으로 풀어야 해서 발 동동 구르고 있습니다 ㅠㅠ
좀 더 생각해보겠습니다 ㅎㅎ!
혹시몰라 해당문제 URL 남겨보겠습니다!
https://programmers.co.kr/app/with_setting/tests/120812/challenges/databases/166
결과로 1,2,5 만 나와야 한다면?
문제 출제자의 답도 틀린게 아닐까요?
4번은 3번과 겹치지만 3번은 취소이므로 4번은 예약 가능합니다.
결과로 1,2,5 만 나와야 한다면?
애초에 문제의 가정 자체가 잘못 설정된 문제로 보입니다.
예약 신청 후 순차적으로 확정하는 프로세스에는 맞지가 않습니다.
네 1,2,5번만 나와야 합니다 ㅠ!!
음.. 네 로그인이 필요합니다.. ㅎㅎ
url 다시 공유드리자면,
https://certi.programmers.co.kr/about/sample 이 경로에 맨 아래 SQL역랑인증 시작하기 버튼 누르고 3번문제가 질문올린 문제와 동일합니다.
주신 URL 은 접근이 안되네요.
로그인이 필요한 걸까요?
이곳 구루비 퀴즈 게시판 문제도 한번 풀어보세요.
http://gurubee.net/sql/quiz
http://gurubee.net/articles/dbquiz
와 좋은 문제집들이네요 !!
감사합니다 시간날 때 마다 완주해야겠네요 ㅎㅎ!!
WITH RECURSIVE t1 AS
(
WITH reservation AS
(
SELECT 1 id, 101 user_id, '2024-01-10 13' start_time, '2024-01-10 15' end_time
UNION ALL SELECT 2, 201, '2024-01-10 15', '2024-01-10 18'
UNION ALL SELECT 3, 101, '2024-01-10 17', '2024-01-10 23'
UNION ALL SELECT 4, 301, '2024-01-10 19', '2024-01-10 20'
UNION ALL SELECT 5, 401, '2024-01-11 09', '2024-01-11 11'
UNION ALL SELECT 6, 301, '2024-01-11 08', '2024-01-11 12'
)
SELECT id, user_id, start_time, end_time
, 1 st -- 확정여부(1/0)
, CAST(id AS VARCHAR(99)) x -- 확정ID 리스트
FROM reservation
WHERE id = 1
UNION ALL
SELECT b.id, b.user_id, b.start_time, b.end_time
, CASE WHEN EXISTS (SELECT 1
FROM reservation c
WHERE FIND_IN_SET(c.id, a.x)
AND c.start_time < b.end_time
AND c.end_time > b.start_time
)
THEN 0 ELSE 1 END st
, CASE WHEN EXISTS (SELECT 1
FROM reservation c
WHERE FIND_IN_SET(c.id, a.x)
AND c.start_time < b.end_time
AND c.end_time > b.start_time
)
THEN a.x ELSE CONCAT(a.x, ',', b.id) END x
FROM t1 a
INNER JOIN reservation b
ON b.id = a.id + 1
)
SELECT *
FROM t1
-- WHERE st = 1
;
와....참고하겠습니다 ㅠㅠ 정말 감사합니다.