복붙노트

[SQL] SQL 서버에서 한 달에 한 행으로 분할 날짜 범위

SQL

SQL 서버에서 한 달에 한 행으로 분할 날짜 범위

나는 두 개의 열이있는 테이블이 "FROM_DATE"와 "TO_DATE"라는이

    the table look like:-

내가 좋아하는 결과를 원하는 : -

from_date            to_date   
-----------         ------------  
2013-11-25           2013-11-30
2013-12-01           2013-12-05

그 날짜는 다음과 같이 나눌 수 있나요 ... 2013년 11월 25일에서 2013년 11월 30일에 분할 및 2013년 12월 5일에 2013년 12월 1일에서 다른 날짜 분할입니까?

해결법

  1. ==============================

    1.이 윤년 안전하고 핸들 날짜는 다른 답변은하지 않는 범위.

    이 윤년 안전하고 핸들 날짜는 다른 답변은하지 않는 범위.

    DECLARE @d TABLE(from_date DATE, to_date DATE);
    
    INSERT @d VALUES ('2013-11-25','2013-12-05');
    
    ;WITH n(n) AS 
    (
      SELECT ROW_NUMBER() OVER (ORDER BY [object_id])-1 FROM sys.all_columns
    ),
    d(n,f,t,md,bp,ep) AS 
    (
      SELECT n.n, d.from_date, d.to_date, 
        DATEDIFF(MONTH, d.from_date, d.to_date),
        DATEADD(MONTH, n.n, DATEADD(DAY, 1-DAY(from_date), from_date)),
        DATEADD(DAY, -1, DATEADD(MONTH, 1, DATEADD(MONTH, n.n, 
          DATEADD(DAY, 1-DAY(from_date), from_date))))
     FROM n INNER JOIN @d AS d 
     ON d.to_date >= DATEADD(MONTH, n.n-1, d.from_date)
    )
    SELECT original_from_date = f, original_to_date = t, 
      new_from_date = CASE n WHEN 0  THEN f ELSE bp END,
      new_to_date   = CASE n WHEN md THEN t ELSE ep END 
    FROM d WHERE md >= n
    ORDER BY original_from_date, new_from_date;
    

    결과 :

    original_from_date   original_to_date   new_from_date   new_to_date
    ------------------   ----------------   -------------   -----------
    2013-11-25           2013-12-05         2013-11-25      2013-11-30
    2013-11-25           2013-12-05         2013-12-01      2013-12-05
    

    더 이상 날짜 범위와 도약 년 SQLFiddle 데모

  2. ==============================

    2.당신이 차원 데이터웨어 하우스에서 작업하는 경우, 날짜 차원을 사용합니다. 그렇지 않으면, CTE를 사용합니다.

    당신이 차원 데이터웨어 하우스에서 작업하는 경우, 날짜 차원을 사용합니다. 그렇지 않으면, CTE를 사용합니다.

    WITH cte AS
    (SELECT from_date
          , to_date
          , from_date AS mo_from_date
          , DATEADD(day, day(from_date)* -1 + 1, from_date) AS bom_date
       FROM DateTable
    UNION ALL
    SELECT from_date
         , to_date
         , DATEADD(month,1,bom_date)
         , DATEADD(month,1,bom_date)
      FROM cte
     where DATEADD(month,1,mo_from_date) < to_date
    )
    SELECT mo_from_date
         , CASE when to_date < DATEADD(month,1,bom_date) THEN
               to_date
           ELSE
               DATEADD(day, -1, DATEADD(month,1,bom_date))
           END AS mo_to_date
      FROM cte
    
  3. from https://stackoverflow.com/questions/20269917/split-date-range-into-one-row-per-month-in-sql-server by cc-by-sa and MIT license