@ddukbbok_kang

하고 싶은 건 일단 해봅니다.

SQL/HackerRank

[해커랭크 medium] SQL Project Planning(카테시안 곱)(MySQL)

강떡볶 2022. 3. 16. 14:34

https://www.hackerrank.com/challenges/sql-projects/problem?isFullScreen=true 

 

SQL Project Planning | HackerRank

Write a query to output the start and end dates of projects listed by the number of days it took to complete the project in ascending order.

www.hackerrank.com

 

select start_date, min(end_date)
from(select start_date 
     from projects 
     where start_date not in (select end_date from projects)) a,
     (select end_date 
     from projects 
     where end_date not in (select start_date from projects)) b
where start_date < end_date
group by start_date
order by min(end_date)-start_date asc, start_date

이 문제를 처음에 풀 때 lead, lag 함수를 이용할 수 있지 않을까 싶어서 lead, lag 함수를 죽어라 팠다.

근데 아니었다 ㅠㅠ 결국 이 함수를 사용해서 문제를 풀 수는 없었다..

 

그래서 다른 분의 풀이를 참고했다.

여기서 규칙은, 연속된 날의 시작일과 종료일은 서로 각 열에 존재하지 않는다는 것이다.

무슨 말이냐면, 위 테이블을 보면 2015-10-01, 2015-10-02, 2015-10-03, 2015-10-04는 연속적이다.

그래서 이 연속적인 기간의 시작일(2015-10-01)은 end_date열에 존재하지 않고, 종료일(2015-10-04)는 start_date열에 존재하지 않는다.

그래서 위 쿼리에서 not in을 통해 각 열에 존재하지 않는 값들만 뽑은 것이다!

select start_date, end_date
from(select start_date 
     from projects 
     where start_date not in (select end_date from projects)) a,
     (select end_date 
     from projects 
     where end_date not in (select start_date from projects)) b

쿼리를 일단 이렇게 실행해본다고 했을 때, end_date에 존재하지 않는 start_date 값과 start_date에 존재하지 않는 end_date 값의 카테시안 곱이 발생한다.

나는 이부분이 제일 이해가 안갔다 ㅠㅠ 그냥 두 개의 테이블에서 각 열을 뽑는 건 줄 알았는데 단순히 그게 아니었다... 각 열을 뽑아서 카테시안 곱을 하기 때문에 모든 경우의 수가 나오는 것이다..

 

https://stricky.tistory.com/245

 

sql 독학 강의 # Cartesian Product 카티션 곱 ansi SQL 문법 12편 -sTricky

sql 독학 강의 # Cartesian Product 카티션 곱 ansi SQL 문법 12편 -sTricky 컨텐츠 index 0. Cartesian Product, 카티션곱 의 정의 1. 카티션곱 활용방법 2. 카티션곱 SQL 작성방법 SQL 독학 강의 오늘은 join의..

stricky.tistory.com

카테시안 곱은 위 링크를 참고하면 좋다.

 

 

아무튼, 그래서 end_date에 존재하지 않는 start_date 값과 start_date에 존재하지 않는 end_date 값의 모든 경우의 수가 나왔으니 필터링을 해줘야된다. start_date는 end_date보다 늦을 수 없으니 where start_date < end_date 조건을 추가한다. 그리고 group by로 start_date를 묶어주고, start_date별 end_date의 최소 날짜를 구하면 연속된 날짜의 start_date와 end_date가 출력된다.

정렬 기준은 연속된 기간을 오름차순으로, 연속된 기간이 같다면 start_date를 오름차순으로 하라고 했으므로 order by를 추가해준다.

 

이 문제 쉬운듯 하면서도 아직 sql 초보인 나에게는 어렵고 헷갈린다ㅠㅠ😅

그래도 이제 어느 정도 이해했다!!!