【问题标题】:Get All Dates of Given Month and Year in SQL Server在 SQL Server 中获取给定月份和年份的所有日期
【发布时间】:2016-05-04 12:21:06
【问题描述】:

我想通过在 SQL Server 中声明月份和年份来获取所有日期。

谁能分享几行简单的 SQL 代码来获取它。

例如:

DECLARE @month AS INT = 5
DECLARE @Year AS INT = 2016
SELECT * from Something

我已经尝试过以下事情,

DECLARE @month TINYINT=5

;WITH CTE_Days AS (
    SELECT DATEADD(
               MONTH,
               @month,
               DATEADD(
                   MONTH,
                   -MONTH(GETDATE()),
                   DATEADD(
                       DAY,
                       -DAY(GETDATE()) + 1,
                       CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)
                   )
               )
           ) Dates
    UNION ALL
    SELECT DATEADD(DAY, 1, Dates)
    FROM   CTE_Days
    WHERE  Dates < DATEADD(
               DAY,
               -1,
               DATEADD(
                   MONTH,
                   1,
                   DATEADD(
                       MONTH,
                       @month,
                       DATEADD(
                           MONTH,
                           -MONTH(GETDATE()),
                           DATEADD(
                               DAY,
                               -DAY(GETDATE()) + 1,
                               CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)
                           )
                       )
                   )
               )
           )
)
SELECT Dates
FROM   CTE_Days

但我正在寻找行数更少且答案简短的简单解决方案

【问题讨论】:

  • 您需要在数据库中创建一个日期表。然后您就可以使用 BETWEEN 函数进行链接了。
  • 请投反对票的原因!
  • “这个问题没有显示任何研究工作”。在这里提问之前您尝试过什么?
  • 我自己不是反对者,但我怀疑原因是asked before。您可以使用日历/日期表、计数表或递归 CTE。其中我推荐date table。这些非常方便,尤其是在报告方面。
  • 已更改为赞成票 :)

标签: sql-server sql-server-2012


【解决方案1】:

与 t-clausen 方法相同,但更紧凑:

Declare @year int = 2017, @month int = 11;
WITH numbers
as
(
    Select 1 as value
    UNion ALL
    Select value + 1 from numbers
    where value + 1 <= Day(EOMONTH(datefromparts(@year,@month,1)))
)
SELECT datefromparts(@year,@month,numbers.value) Datum FROM numbers

【讨论】:

    【解决方案2】:

    您不能仅通过声明月份来获得所有天数,由于闰年,您还需要添加年份:

    DECLARE @date DATE = getdate()
    
    ;WITH N(N)AS 
    (SELECT 1 FROM(VALUES(1),(1),(1),(1),(1),(1))M(N)),
    tally(N)AS(SELECT ROW_NUMBER()OVER(ORDER BY N.N)FROM N,N a)
    SELECT top(day(EOMONTH(@date)))
      N day,
      dateadd(d,N-1, @date) date
    FROM tally
    

    另一个不同的解决方案(通过 t@clausen):

    DECLARE @month AS INT = 5
    DECLARE @Year AS INT = 2016
    
    ;WITH N(N)AS 
    (SELECT 1 FROM(VALUES(1),(1),(1),(1),(1),(1))M(N)),
    tally(N)AS(SELECT ROW_NUMBER()OVER(ORDER BY N.N)FROM N,N a)
    SELECT N day,datefromparts(@year,@month,N) date FROM tally
    WHERE N <= day(EOMONTH(datefromparts(@year,@month,1)))
    

    【讨论】:

    • 感谢您的回答!它有助于对我的要求进行一些更改。所以现在我又添加了一个可变年份来获取所有日期。
    • @pedram 我删除了您在答案中更改的部分,因为它总是返回 36 天,还添加了一个新答案,您可以在指定要求后改用它
    • 现在它返回 30 行 :( 它应该返回 31 行 :)
    • 现已修复。将 N
    • 查询几乎无法阅读,并且没有说明您为实现解决方案所做的工作。
    【解决方案3】:

    如果您有日期/时间列,则使用month() 函数:

    select t.*
    from t
    where month(datecol) = 5;
    

    【讨论】:

    • 不,我将日期作为表中的数据类型。以上查询返回我的表中存在的日期。
    • 我认为这里的问题是制作日期表
    【解决方案4】:

    另一个基于 CTE 的版本

    DECLARE @Month INT = 2, @Year INT = 2019
    
    ;WITH MonthDays_CTE(DayNum)
    AS
    (
    SELECT DATEFROMPARTS(@Year, @Month, 1) AS DayNum
    UNION ALL
    SELECT DATEADD(DAY, 1, DayNum)
      FROM MonthDays_CTE
      WHERE DayNum < EOMONTH(DATEFROMPARTS(@Year, @Month, 1))
    )
    SELECT *
      FROM MonthDays_CTE
    

    【讨论】:

      【解决方案5】:

      您可以使用以下查询获取一个月的所有日期。

      declare @month int, @year int
      set @month = 2
      set @year = 2008
      
      SELECT
      CAST(CAST(@year AS VARCHAR) + '-' + CAST(@Month AS VARCHAR) + '-01' AS DATETIME) + Number
      FROM master..spt_values
      WHERE type = 'P'
      AND
      (CAST(CAST(@year AS VARCHAR) + '-' + CAST(@Month AS VARCHAR) + '-01' AS DATETIME) + Number )
      <
      DATEADD(mm,1,CAST(CAST(@year AS VARCHAR) + '-' + CAST(@Month AS VARCHAR) + '-01' AS DATETIME) )
      

      希望这会对你有所帮助。

      【讨论】:

        【解决方案6】:
        DECLARE @MonthNo TINYINT = 03 -- set your month
            ,@WOYEAR SMALLINT = 2018; -- set your year
        
        IF OBJECT_ID('TEMPDB..#TMP') IS NOT NULL
            DROP TABLE #TMP
        
        DECLARE @START_DATE DATETIME
            ,@END_DATE DATETIME
            ,@CUR_DATE DATETIME
        
        SET @START_DATE = DATEADD(month, @MonthNo - 1, DATEADD(year, @WOYEAR - 1900, 0))
        SET @END_DATE = DATEADD(day, - 1, DATEADD(month, @MonthNo, DATEADD(year, @WOYEAR - 1900, 0)))
        SET @CUR_DATE = @START_DATE
        
        CREATE TABLE #TMP (
            WEEKDAY VARCHAR(10)
            ,DATE INT
            ,MONTH VARCHAR(10)
            ,YEAR INT
            ,dates VARCHAR(25)
            )
        
        WHILE @CUR_DATE <= @END_DATE
        BEGIN
            INSERT INTO #TMP
            SELECT DATENAME(DW, @CUR_DATE)
                ,DATEPART(DAY, @CUR_DATE)
                ,DATENAME(MONTH, @CUR_DATE)
                ,DATEPART(YEAR, @CUR_DATE)
                ,REPLACE(CONVERT(VARCHAR(9), @CUR_DATE, 6), ' ', '-')
        
            SET @CUR_DATE = DATEADD(DD, 1, @CUR_DATE)
        END
        
        SELECT *
        FROM #TMP
        

        【讨论】:

          【解决方案7】:
          DECLARE @Today DATE= GETDATE() ,
          @StartOfMonth DATE ,
          @EndOfMonth DATE;
          
          DECLARE @DateList TABLE ( DateLabel VARCHAR(10) );
          SET @EndOfMonth = EOMONTH(GETDATE());
          SET @StartOfMonth = DATEFROMPARTS(YEAR(@Today), MONTH(@Today), 1);
          
          WHILE @StartOfMonth <= @EndOfMonth
          BEGIN
             INSERT  INTO @DateList
             VALUES  ( @StartOfMonth );
             SET @StartOfMonth = DATEADD(DAY, 1, @StartOfMonth);
          END;
          
          SELECT  DateLabel
          FROM    @DateList; 
          

          【讨论】:

            【解决方案8】:
            WHERE Dates LIKE '2018-12%'
            

            在日期时间或时间戳中,它是年月,因此这将在 12 月提取与 2018 年匹配的所有内容。您也可以修改它以使用您的变量。

            @month = 12;
            @year = 2018;
            @searchQuery = @year + @month + '%';
            
            WHERE Dates LIKE @searchQuery
            

            【讨论】:

              【解决方案9】:

              小改动。 @t-clausen.dk 给出的查询只有在您在本月的第一天运行时才会给您正确的结果。只需稍加改动,效果就很棒。

              DECLARE @date DATE = getdate()
              
              ;WITH N(N)AS 
              (SELECT 1 FROM(VALUES(1),(1),(1),(1),(1),(1))M(N)),
              tally(N)AS(SELECT ROW_NUMBER()OVER(ORDER BY N.N)FROM N,N a)
              
              
              SELECT top(day(EOMONTH(@date)))
               N day,
               DATEFROMPARTS(year(@date),month(@date), n) date
              FROM tally
              

              顺便说一句,t-clausen.dk 不错。我想不出更简单的方法

              【讨论】:

                【解决方案10】:

                这是一个查询:

                DECLARE @ReportDate VARCHAR(20)='2019-02-10'
                
                DECLARE @LastDay INT =DAY(EOMONTH(@ReportDate))
                
                DECLARE @DayStart INT=01
                
                CREATE TABLE #TEMPMonth ([MDay] VARCHAR(20))
                
                WHILE @LastDay>=@DayStart
                
                BEGIN
                    
                INSERT INTO #TEMPMonth 
                    
                SELECT CAST(CAST(YEAR(@ReportDate)AS VARCHAR)+'-'+CAST(MONTH(@ReportDate)AS VARCHAR)+'-'+CAST(@DayStart AS VARCHAR) AS DATE)
                    SET @DayStart+=1
                
                END
                
                SELECT * FROM #TEMPMonth
                
                DROP TABLE #TEMPMonth
                

                【讨论】:

                  【解决方案11】:
                  CREATE FUNCTION fn_GetMonthlyDates
                  (
                    @ProcessDate smalldatetime
                  )
                  RETURNS @LOAN TABLE 
                  (
                   ProcessDate    smalldatetime
                  )
                  AS
                  BEGIN
                      DECLARE 
                          @Today DATE= @ProcessDate,
                          @StartOfMonth DATE ,
                          @EndOfMonth DATE;
                  
                      DECLARE @DateList TABLE (DateLabel VARCHAR(10) );
                      SET @EndOfMonth = EOMONTH(@Today);
                      SET @StartOfMonth = DATEFROMPARTS(YEAR(@Today), MONTH(@Today), 1);
                  
                      WHILE @StartOfMonth <= @EndOfMonth
                      BEGIN
                         INSERT  INTO @DateList
                         VALUES  (@StartOfMonth );
                         SET @StartOfMonth = DATEADD(DAY, 1, @StartOfMonth);
                      END;
                  
                      INSERT INTO @LOAN(ProcessDate)
                      SELECT  DateLabel
                      FROM    @DateList; 
                  
                  RETURN
                  END
                  

                  【讨论】:

                  • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。
                  【解决方案12】:

                  这是另一种方式,但结果相同。

                  declare @year int=2021,@month int=3
                  
                  select  DATEADD(dd,a.n-1,datefromparts(@year,@month,1)) 
                  from    (
                           select top 31 ROW_NUMBER() over (order by a.object_id) as n
                           from   sys.all_objects a
                        ) a where DATEPART(mm,DATEADD(dd,a.n-1,datefromparts(@year,@month,1)))=3
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-12-05
                    • 2021-07-17
                    • 2010-09-07
                    • 2014-07-09
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-01-19
                    相关资源
                    最近更新 更多