복붙노트

[SQL] 두 날짜 사이의 개월

SQL

두 날짜 사이의 개월

SQL에서 두 날짜 사이의 월 이름을 얻을 수 있습니다

즉,  2011-05-01과 2011-08-01는 입력입니다 난 그냥 출력으로 원하는

------------
Month
------------
May
June
July
August

어떤 몸이 알고있는 경우가 주를 기쁘게 쿼리합니다.

해결법

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

    1.

    DECLARE @StartDate  DATETIME,
            @EndDate    DATETIME;
    
    SELECT   @StartDate = '20110501'        
            ,@EndDate   = '20110801';
    
    
    SELECT  DATENAME(MONTH, DATEADD(MONTH, x.number, @StartDate)) AS MonthName
    FROM    master.dbo.spt_values x
    WHERE   x.type = 'P'        
    AND     x.number <= DATEDIFF(MONTH, @StartDate, @EndDate);
    

    결과 :

    MonthName
    ------------------------------
    May
    June
    July
    August
    
    (4 row(s) affected)
    
  2. ==============================

    2.당신은 날짜의 테이블을 구축하고, 각에서 월 이름을 얻어서, 재귀 CTE하여이 작업을 수행 할 수 있습니다 :

    당신은 날짜의 테이블을 구축하고, 각에서 월 이름을 얻어서, 재귀 CTE하여이 작업을 수행 할 수 있습니다 :

    declare @start DATE = '2011-05-01'
    declare @end DATE = '2011-08-01'
    
    ;with months (date)
    AS
    (
        SELECT @start
        UNION ALL
        SELECT DATEADD(month,1,date)
        from months
        where DATEADD(month,1,date)<=@end
    )
    select Datename(month,date) from months
    
  3. ==============================

    3.나는 출력 Jamiec의 대답뿐만 아니라 달의 마지막 날을 수정했습니다.

    나는 출력 Jamiec의 대답뿐만 아니라 달의 마지막 날을 수정했습니다.

    declare @start DATE = '2014-05-01'
    declare @end DATE = getdate()
    
    ;with months (date)
    AS
    (
        SELECT @start
        UNION ALL
        SELECT DATEADD(month, 1, date)
        from months
        where DATEADD(month, 1, date) < @end
    )
    select     [MonthName]    = DATENAME(mm, date),
               [MonthNumber]  = DATEPART(mm, date),  
               [LastDayOfMonth]  = DATEPART(dd, EOMONTH(date)),
               [MonthYear]    = DATEPART(yy, date)
    from months
    

    어떤 출력을 제공합니다 :

    MonthName   MonthNumber LastDayOfMonth  MonthYear
    May         5           31              2014
    June        6           30              2014
    July        7           31              2014
    August      8           31              2014
    September   9           30              2014
    
  4. ==============================

    4.Jamiec의 대답에 의해 영감을, 그러나 더 큰 일에서 하루와 함께 문제를 해결 :

    Jamiec의 대답에 의해 영감을, 그러나 더 큰 일에서 하루와 함께 문제를 해결 :

    declare @start DATE
    declare @end DATE 
    
    SELECT  @start='2011-05-19' , @end='2011-08-15' 
    
    ;with months (date)
    AS
    (
       SELECT DATEADD(DAY,1,EOMONTH(@start,-1))
        UNION ALL
        SELECT DATEADD(month,1,date)
        from months
        where DATEADD(month,1,date) < EOMONTH(@end)
    )
    select Datename(month,date)
    from months
    
  5. ==============================

    5.

        declare @start DATE = '2011-05-30'
        declare @end DATE = '2011-06-10' 
       ;with months (date)
        AS
        (
            SELECT @start
            UNION ALL
            SELECT DATEADD(month,1,date)
            from months
            where DATEADD(month,1,date)<= DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@end)+1,0))
        )
        select Datename(month,date) from months
    
  6. ==============================

    6.잘, @bogdhan sahlean이 좋은 세트 기반 솔루션을 부여하지만 MSDN에서 연도 범위에 9999-12-31 0001-01-01 자료형 일시 DATETIME2을 고려하여 2,048 개까지의 값을 제한했다

    잘, @bogdhan sahlean이 좋은 세트 기반 솔루션을 부여하지만 MSDN에서 연도 범위에 9999-12-31 0001-01-01 자료형 일시 DATETIME2을 고려하여 2,048 개까지의 값을 제한했다

    이 극단적 인 사례지만 가치가 알고있는 경우에도. 어느 날 누군가가 170 ​​년 이상 개월 이상 프로젝트하려고하면 무엇부터 :)

    심지어 가장 upvoted 답변은 어떤 가장자리 케이스를 이행하지 않는 일을 시작할 때 (> 종료 날짜, 종료 날짜의 월을 표시하지 않습니다 또한 재귀 쿼리는 기본적으로 100 개 실행) 후 실패합니다. 또한 다량으로 사용하는 경우 성능 돼지입니다 반복에 대한 재귀 CTE를 사용.

    이제, 더 나은 솔루션 (IMHO)는 두 날짜 사이의 개월을 생성하기 위해 일정 테이블이나 집계 테이블을 사용하는 것입니다. 하나의 테이블을 작성할 수없는 경우, 사용에 더 나은 대안이있다 번호 테이블을 생성하기위한 CTE 계단식 Itzik 벤 간스. (여기) 어느 것이 더 빨리, 더 논리적, 물리적 읽기, 아니 작업 테이블 NADA 없다

    여기에 코드입니다

    DECLARE @start DATETIME2 = '00010101'
    DECLARE @end DATETIME2 = '99991231'
    ;WITH lv0 AS (SELECT 0 g UNION ALL SELECT 0)
        ,lv1 AS (SELECT 0 g FROM lv0 a CROSS JOIN lv0 b) -- 4
        ,lv2 AS (SELECT 0 g FROM lv1 a CROSS JOIN lv1 b) -- 16
        ,lv3 AS (SELECT 0 g FROM lv2 a CROSS JOIN lv2 b) -- 256
        ,lv4 AS (SELECT 0 g FROM lv3 a CROSS JOIN lv3 b) -- 65,536
        ,lv5 AS (SELECT 0 g FROM lv4 a CROSS JOIN lv4 b) -- 4,294,967,296
        ,Tally (n) AS (SELECT 0 UNION SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM lv5)
    SELECT DATENAME(YEAR,DATEADD(MONTH,N,@start)) AS [Year Part], DATENAME(MONTH,DATEADD(MONTH,n,@start)) AS [Month Part]
    FROM Tally where N between 0 and DATEDIFF(mm,@start,@end)  
    ORDER BY n;
    

    NB : 나는 0 일 위치에서 숫자를 시작하는 SELECT 0 추가

    내 PC에 표시된 성능은

    Itzik 방법

    의 시간이 소요 여기에 주어진 재귀 솔루션 중 하나

    집계 테이블, 달력 테이블과 itzik 번호 테이블 사이의 성능은 약간 다를 수 있지만, 사용자가 제공하는 모든 날짜 범위와 매력처럼 작동 할 수 있습니다.

  7. ==============================

    7.다음과 같은 데이터베이스 함수를 만듭니다

    다음과 같은 데이터베이스 함수를 만듭니다

    CREATE FUNCTION [dbo].[DateRange] 
    (@Identifier CHAR(1),@StartDate DATETIME,@EndDate DATETIME)
    RETURNS @SelectedRange TABLE(Dates DATE) AS
     BEGIN
    
       ;WITH cteRange (DateRange) AS (
       SELECT @StartDate
         UNION ALL
       SELECT
         CASE
             WHEN Upper(@Identifier) = 'H' THEN DATEADD(hh, 1, DateRange)
             WHEN Upper(@Identifier) = 'D' THEN DATEADD(dd, 1, DateRange)
             WHEN Upper(@Identifier) = 'W' THEN DATEADD(ww, 1, DateRange)
             WHEN Upper(@Identifier) = 'M' THEN DATEADD(mm, 1, DateRange)
             WHEN Upper(@Identifier) = 'Y' THEN DATEADD(yy, 1, DateRange)
         END
       FROM cteRange
       WHERE DateRange <=
        CASE
            WHEN Upper(@Identifier) = 'H' THEN DATEADD(hh, -1, @EndDate)
            WHEN Upper(@Identifier) = 'D' THEN DATEADD(dd, -1, @EndDate)
            WHEN Upper(@Identifier) = 'W' THEN DATEADD(ww, -1, @EndDate)
            WHEN Upper(@Identifier) = 'M' THEN DATEADD(mm, -1, @EndDate)
            WHEN Upper(@Identifier) = 'Y' THEN DATEADD(yy, -1, @EndDate)
        END)
     INSERT INTO @SelectedRange (Dates) SELECT DateRange FROM cteRange
      OPTION (MAXRECURSION 3660);
    RETURN
    END
    

    기능을 사용하여 우리는 날짜의 범위를 생성 할 수 있습니다

    SELECT * from dbo.DateRange('M','1953-01-01','2019-01-01')
    

    우리는 출력을 포맷하려면 우리가 예를 들어 아래와 같은 테이블 변수에 결과를 저장할 수 있습니다,

    DECLARE @tblDateRange TABLE (AutoID INT IDENTITY(1,1),DateRange DATE)
    INSERT INTO @tblDateRange SELECT * from dbo.DateRange('M','1953-01-01','2019-01-01')
    SELECT 
    LEFT(DATENAME(MONTH,DateRange),3) [MonthYearValue],YEAR(DateRange) AS [Year]
    FROM @tblDateRange
    

    우리가 변경할 수 있습니다 우리의 필요에 따라

    OPTION (MAXRECURSION 3660)
    
  8. ==============================

    8.이 시도:

    이 시도:

    declare 
           @sd date=getdate(),
           @ld date='2016-01-01'
    
    select 
         Datename(month,dateadd(month,number,GETDATE())), 
         number
    from master.dbo.spt_values 
    where type='p' 
         and dateadd(month,number,GETDATE()) <= @ld
    
  9. from https://stackoverflow.com/questions/7885851/months-between-two-dates by cc-by-sa and MIT license