HackerRank Intermediate
- SQL Project Planning
WITH CTE AS (
SELECT Task_ID, Start_Date, End_Date
FROM Projects
WHERE End_Date NOT IN (SELECT Start_Date FROM Projects)
ORDER BY Start_Date
),
CTE_2 AS (
SELECT
t1.Task_ID, t1.Start_Date, t1.End_Date, t2.Start_Date AS Start_Date_2, t2.End_Date AS End_Date_2
FROM
Projects t1 LEFT OUTER JOIN CTE t2
ON t1.task_ID = t2.task_ID
),
CTE_3 AS (
SELECT
Task_ID,
RANK() OVER(ORDER BY Start_Date) AS rnk,
CASE
WHEN Task_ID = 1 THEN Start_Date
WHEN Task_ID !=1 AND (LAG(End_Date_2, 1) OVER (ORDER BY Start_Date)) IS NOT NULL THEN Start_Date
END as new_Start_Date,
CASE
WHEN End_Date_2 IS NOT NULL THEN End_Date_2
END AS new_End_Date
FROM
CTE_2
),
CTE_4 AS (
SELECT
new_Start_Date AS Start_Date,
CASE
WHEN new_End_Date IS NULL THEN LEAD(new_End_Date, 1) OVER (ORDER BY rnk)
ELSE new_End_Date
End AS End_Date
FROM
CTE_3
WHERE
new_Start_Date IS NOT NULL OR new_End_Date IS NOT NULL
)
SELECT *
FROM CTE_4
WHERE Start_Date IS NOT NULL
ORDER BY TIMESTAMPDIFF(DAY, DATE(End_Date), DATE(Start_Date)) DESC, Start_Date
[문제 상황]
- Task별로 Start_Date, End_Date가 한 행에 무조건 1일 차이로 집계된다. (같은 행의 End_Date - Start_Date = 1일)
- 같은 프로젝트 Task더라도 Task_ID로 구분되며, 프로젝트 관련 식별자가 존재하지 않아서 한번에 프로젝트별 기간 산출 불가
- 시간순으로 정렬했을 때, 한 행의 End_Date와 바로 다음 행의 Start_Date가 같지 않을 때가 프로젝트로 구분되는 시점
[해결]
<해결 아이디어>
- End_Date가 Start_Date 리스트에 없는 시점이 프로젝트 구분 시기이다. (구분 시점의 End_Date 먼저 구하기)
End_Date NOT IN (SELECT Start_Date FROM Projects)
으로 CTE1 생성
- 프로젝트 구분 시점의 End_Date와 본래 테이블을 병합하여 프로젝트 시작 날짜를 가져올 수 있도록 한다.
- 원래 테이블에
LEFT OUTER JOIN
으로 CTE1 병합 : CTE2 생성
- 원래 테이블에
- CTE2의
t2.End_Date
컬럼에서 직전 행에 데이터가 존재하지 않는 행의t1.Start_Date
가 프로젝트 시작점이 된다.- Task_ID가 1이 아닌 경우에 대해서 LAG함수를 활용 : CTE3 생성
- 데이터 모든 행에 NULL이 존재하므로 정렬을 활용할 수 있도록 하기 위해 rnk 컬럼 생성
- CTE3에서 rnk컬럼으로 오름차순 정렬했을 때,
new_Start_Date
,new_End_Date
가 NULL이 아닌 데이터 중에서new_End_Date
가 NULL이면 다음 행의new_End_Date
가 프로젝트의 종료 시점이 된다.- LEAD함수 활용하여 프로젝트 종료 시점 구하기
- CTE3의
new_Start_Date
,new_End_Date
가 NULL이 아닌 데이터 : 프로젝트 시작 시점의 Start_Date 데이터만 남김 : CTE4 생성
- CTE4에서 Start_Date가 NULL인 경우를 제외하고 정렬하면 원하는 결과 도출
[회고]
- CTE를 적게쓰거나 쓰지않고 더 간편하게 해결하는 방법은 없었을까?
- 다른 프로그래밍 언어와 마찬가지로 <코드작성 - 실행 - 결과 관찰 - 디버깅 및 수정 - 결과 관찰 - ...> 을 반복하며 원하는 결과를 차근차근 얻어갈 수 있다.
- 하지만 비용(효율, 시간 등) 감소를 위해 더 간단하게 해결할 수 있는 로직을 연구해야한다.
'DA Study > TIL' 카테고리의 다른 글
[TIL] SQL Project Planning 간단 풀이 # MySQL # SQL (0) | 2025.04.09 |
---|---|
[TIL] 재귀 쿼리 (Recursive CTE) # MySQL # SQL (0) | 2025.04.06 |
[TIL] 리스트에서 요소 개수 카운트하기, 문자열 길이 반환 함수(CHAR_LENGTH) 활용 #SQL #MySQL (0) | 2025.03.18 |
[TIL] 이스케이핑(ESCAPING)의 개념 및 활용 예시 #SQL #MySQL (0) | 2025.03.10 |
[TIL] 윈도우 함수에서 ROWS로 특정 범위내 데이터 지정하기 #SQL #SQLite #solvesql (0) | 2025.03.06 |