代码之家  ›  专栏  ›  技术社区  ›  beta

TSQL根据开始和结束日期生成月份

  •  0
  • beta  · 技术社区  · 8 年前

    我有两个变量 start end 包含日期值,例如。 2018-05-01 2019-02-28 . 我想创建一个表,其中包含介于两者之间的每个月。结果表应如下所示。

    Month   Year
    5       2018
    6       2018
    7       2018
    8       2018
    9       2018
    10      2018
    11      2018
    12      2018
    01      2019
    02      2019
    

    如何才能做到这一点?

    2 回复  |  直到 8 年前
        1
  •  1
  •   David Shorthose    8 年前

    下面是我在MS-SQL中使用的一个表函数

    CREATE FUNCTION [dbo].[GetSequencedMonthSplit](@StartDate DATETIME, @EndDate DATETIME)
    RETURNS @Results TABLE 
    (
        ID INT IDENTITY(1,1) 
        , YearValue INT 
        , MonthValue INT 
        , MonthName NVARCHAR(50) 
    
    )
    AS
    
    BEGIN 
    
    
    
    IF @StartDate IS NULL OR @EndDate IS NULL 
    BEGIN 
        /*GET THE CURRENT CALENDAR YEAR*/
        SELECT 
            @StartDate = DATEFROMPARTS(year(getdate()),1,1)
            ,@EndDate = DATEFROMPARTS(year(getdate()),12,31)
    END 
    
    
    
    WHILE @StartDate < @EndDate 
    BEGIN 
         INSERT INTO @Results (YearValue, MonthValue, MonthName) 
         SELECT 
            DATEPART(year, @StartDate)
            , DATEPART(month, @StartDate) 
            , DATENAME(month,@StartDate) 
    
    
    
    
        SET @StartDate = DATEADD(month, 1, @StartDate) 
    END 
    
    
        RETURN  
    
    
    END
    

    然后打这样的电话:

    select 
        MonthValue AS [Month]
      , YearValue  as [Year]
    from 
        dbo.GetSequencedMonthSplit(@StartDate,@EndDate)
    

        2
  •  0
  •   Alan Burstein    8 年前

    杰伦·莫斯特在你的评论中提出的解决方案是最好的办法。大卫的解决方案会让你得到你想要的,但他的作用是 Multi-statement inline 表值函数 for the reasons outlined here . 即使您只处理一小部分行,多语句也会影响使用调用它们的查询的性能。

    创建 内联 表值函数(iTVF)您只需要了解 tally tables 工作。这样做会改变你的职业。你要找的iTVF版本如下:

    CREATE FUNCTION dbo.MonthYearRange (@startdate DATE, @enddate DATE)
    RETURNS TABLE WITH SCHEMABINDING AS RETURN
    WITH L1   AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) x(N)),
    iTally(N) AS
    ( SELECT 0 UNION ALL
      SELECT TOP (DATEDIFF(MONTH,@startdate,@enddate)) ROW_NUMBER() OVER (ORDER BY (SELECT 1))
      FROM L1 a CROSS JOIN L1 b CROSS JOIN L1 c)
    SELECT [Month] = MONTH(d.dt),
           [Year]  = YEAR(d.dt)
    FROM iTally i
    CROSS APPLY (VALUES (DATEADD(MONTH,i.N,@startdate))) d(dt);
    

    DECLARE @startdate DATE = '2018-05-01',
            @enddate   DATE = '2019-02-28';
    

    返回:

    Month       Year
    ----------- -----------
    5           2018
    6           2018
    7           2018
    8           2018
    9           2018
    10          2018
    11          2018
    12          2018
    1           2019
    2           2019
    
    推荐文章