我必须创建一个程序,将一年中的天数和月份的名称包含在一年中,并且它将从给定年份开始并且将有一个结束年份,例如
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;
这将给出年份,月份和一年中的天数。但我不能填写这个请帮助
答案 0 :(得分:2)
你真正需要担心的唯一一个月是二月。大多数年份平均分为4年是闰年(there are some exceptions)。
此查询硬编码了几个月。要生成我使用recursion的年份列表,因为这可以复制/粘贴。但是,有更好的方法可以做到这一点,包括tally tables和calendar 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