【问题标题】:How to get the number of dates in a month of a range of two years如何获取两年范围内一个月内的日期数
【发布时间】:2018-02-06 16:12:35
【问题描述】:

我必须创建一个程序,该程序将填充年份、一个月的天数和月份的名称,它将从给定的年份开始,并有一个结束年份,例如

YEAR  MONTH DAYS
2015  JAN   31
2015  FEB   28
.
.
2015 DEC    30

这样。 请帮助我如何完成这项工作。我可以像这样确定每年一年中的总月数和天数

declare @y int;
declare @cnt int = 2015;
set @y = 2012;
while @y<@cnt
begin 
SELECT DATEDIFF(MONTH,  cast(@y as char(4)),  cast(@y+1 as char(4)))    Months ,DATEDIFF(DAY,  cast(@y as char(4)),  cast(@y+1 as char(4))) Days ,@y Year
set @y = @y+1;
end;

这将给出一年,它的月数和一年中的天数。但我无法填充这个请帮助

【问题讨论】:

  • 您应该在此处使用计数表而不是循环。但这是为了什么?是作业吗?
  • @SeanLange 不,我的项目中需要这个,你能帮忙吗?请
  • 除了二月之外,每个月的天数总是相同的,所以除了二月,这在查询中是没有意义的。
  • @SeanLange 同意,但我需要这个,你能帮忙吗?

标签: sql-server date stored-procedures


【解决方案1】:

另一个选项,使用master.dbo.spt_values 作为计数表

declare @start int = 2000
declare @end int = 2015

select
    [year]
    , [month] = choose(n, 'JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN'
                        , 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC')
    , [days] = choose(n, 31, iif([year] % 400 = 0 or ([year] % 100 <>0 and [year] % 4 = 0), 29, 28)
                        , 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
from
    master.dbo.spt_values
    cross apply (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) v(n)
    cross apply (select [year] = number + @start) q
where
    type = 'P'
    and number < @end - @start

【讨论】:

  • 你能写一个需要两个参数的程序吗?
【解决方案2】:

您真正需要担心的唯一月份是二月。大多数除以 4 的年份是闰年 (there are some exceptions)。

此查询对月份进行硬编码。要生成我使用过的年份列表recursion,因为可以复制/粘贴。但是,有更好的方法可以做到这一点,包括tally tablescalendar tables,我强烈推荐这两种方法。

DECLARE @StartYear INT = 2000;
DECLARE @EndYear INT = 2020;

WITH 
    Years AS
    (
            SELECT
                @StartYear AS Year

        UNION ALL

            SELECT 
                Year + 1
            FROM
                Years
            WHERE
                Year < @EndYear
    )
SELECT
    y.Year,
    DaysInMonth.Month,
    CASE
        -- Feb logic based on: https://en.wikipedia.org/wiki/Leap_year#Algorithm
        WHEN DaysInMonth.Month = 'Feb' THEN
            CASE 
                WHEN y.Year % 4 = 0 AND y.Year % 100 = 0 AND y.Year % 400 = 0 THEN 29
                WHEN y.Year % 4 = 0 AND y.Year % 100 <> 0 THEN 29
                ELSE 28
            END                
        ELSE DaysInMonth.Days
    END
FROM
    (
        VALUES
            ('Jan', 31),
            ('Feb', 28),
            ('Mar', 31),
            ('Apr', 30),
            ('May', 31),
            ('Jun', 30),
            ('Jul', 31),
            ('Aug', 31),
            ('Sep', 30),
            ('Oct', 31),
            ('Nov', 30),
            ('Dec', 31)
    ) AS DaysInMonth (Month, Days)

    CROSS JOIN Years AS y
;

将其包装在 procedure 中:

CREATE PROCEDURE YourSchema.YourProcedureName
(
    @StartYear INT,
    @EndYear INT
)
AS
    SET NOCOUNT ON;

    WITH
        Years AS
    ...
    CROSS JOIN Years AS y
GO

【讨论】:

  • 已更新。删除两个声明语句并将剩余的查询放在过程模板中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 2017-08-22
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多