如何获得一年两个月的日期数

时间:2018-02-06 16:12:35

标签: sql-server date stored-procedures

我必须创建一个程序,将一年中的天数和月份的名称包含在一年中,并且它将从给定年份开始并且将有一个结束年份,例如

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;

这将给出年份,月份和一年中的天数。但我不能填写这个请帮助

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

另一种选择,使用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