在 SQL 如何根据开始日期和经过的天数计算一年中的天数
In SQL how to calculate days in a year based on a start date and the number of days lapsed
如果我有一个开始日期和已经过去的天数,那么SQL计算每年的天数是多少?
例如日期(ymd) 2013-01-01,经过的天数是1000。
我希望结果看起来像这样
2013 = 365
2014 = 365
2015 = 270
可以像datediff
那样写成函数吗?
我试过使用日历 table,但是当然,链接到这个只会给我 2013 = 1000
我的日历 table 是这样的。
DATE_ID | DATE | CALENDAR_YEAR | FINANCIAL_YEAR
-----------------------------------------------
20130101 | 2013-01-01 | 2013 | 2013/14
这是我试过的。
SELECT
D.FISCAL_YEAR, SUM([DAYS]) AS NUMBER_OF_DAYS
FROM [dbo].[FACT] F
LEFT JOIN [dbo].[DIM_DATE] D ON D.DATE_ID = F.DATE_ID
GROUP BY
D.FISCAL_YEAR
结果是。
FISCAL_YEAR | NUMBER_OF_DAYS
----------------------------
2013/14 |2820
2014/15 |6635
2015/16 |2409
我会亲自建立一个计数 table 来做到这一点。一旦你建立了它,你可以很容易地得到每个日期并计算每年的天数:
DECLARE @YMD date = '20130101',
@Lapsed int = 1000;
--Build a Tally table
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3, N N4), --10,000 should be enough
--Build the dates table
Dates AS(
SELECT DATEADD(DAY, T.I, @YMD) AS CalendarDate
FROM Tally T
WHERE T.I <= @Lapsed - 1)
--And count the days
SELECT DATEPART(YEAR, CalendarDate) AS Year,
COUNT(CalendarDate) AS Days
FROM Dates D
GROUP BY DATEPART(YEAR, CalendarDate);
作为函数:
CREATE FUNCTION CountDays (@YMD date, @Lapsed int)
RETURNS table
AS RETURN
--Build a Tally table
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3, N N4), --10,000 should be enough
--Build the dates table
Dates AS(
SELECT DATEADD(DAY, T.I, @YMD) AS CalendarDate
FROM Tally T
WHERE T.I <= @Lapsed - 1)
--And count the days
SELECT DATEPART(YEAR, CalendarDate) AS Year,
COUNT(CalendarDate) AS Days
FROM Dates D
GROUP BY DATEPART(YEAR, CalendarDate);
GO
SELECT *
FROM (VALUES('20130101',1000),
('20150501',755))V(YMD, Lapsed)
CROSS APPLY dbo.CountDays(V.YMD,V.Lapsed) CD;
一种方法是递归 CTE:
with dates as (
select v.d, 1000 - datediff(day, v.d, dateadd(year, 1, v.d)) as days
from (values (datefromparts(2013, 1, 1))) v(d)
union all
select dateadd(year, 1, d), days - datediff(day, d, dateadd(year, 1, d))
from dates
where days > 0
)
select d,
(case when days > 0 then datediff(day, d, dateadd(year, 1, d))
else datediff(day, d, dateadd(year, 1, d)) + days
end)
from dates;
Here 是一个 db<>fiddle.
如果我有一个开始日期和已经过去的天数,那么SQL计算每年的天数是多少?
例如日期(ymd) 2013-01-01,经过的天数是1000。
我希望结果看起来像这样
2013 = 365
2014 = 365
2015 = 270
可以像datediff
那样写成函数吗?
我试过使用日历 table,但是当然,链接到这个只会给我 2013 = 1000
我的日历 table 是这样的。
DATE_ID | DATE | CALENDAR_YEAR | FINANCIAL_YEAR
-----------------------------------------------
20130101 | 2013-01-01 | 2013 | 2013/14
这是我试过的。
SELECT
D.FISCAL_YEAR, SUM([DAYS]) AS NUMBER_OF_DAYS
FROM [dbo].[FACT] F
LEFT JOIN [dbo].[DIM_DATE] D ON D.DATE_ID = F.DATE_ID
GROUP BY
D.FISCAL_YEAR
结果是。
FISCAL_YEAR | NUMBER_OF_DAYS
----------------------------
2013/14 |2820
2014/15 |6635
2015/16 |2409
我会亲自建立一个计数 table 来做到这一点。一旦你建立了它,你可以很容易地得到每个日期并计算每年的天数:
DECLARE @YMD date = '20130101',
@Lapsed int = 1000;
--Build a Tally table
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3, N N4), --10,000 should be enough
--Build the dates table
Dates AS(
SELECT DATEADD(DAY, T.I, @YMD) AS CalendarDate
FROM Tally T
WHERE T.I <= @Lapsed - 1)
--And count the days
SELECT DATEPART(YEAR, CalendarDate) AS Year,
COUNT(CalendarDate) AS Days
FROM Dates D
GROUP BY DATEPART(YEAR, CalendarDate);
作为函数:
CREATE FUNCTION CountDays (@YMD date, @Lapsed int)
RETURNS table
AS RETURN
--Build a Tally table
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3, N N4), --10,000 should be enough
--Build the dates table
Dates AS(
SELECT DATEADD(DAY, T.I, @YMD) AS CalendarDate
FROM Tally T
WHERE T.I <= @Lapsed - 1)
--And count the days
SELECT DATEPART(YEAR, CalendarDate) AS Year,
COUNT(CalendarDate) AS Days
FROM Dates D
GROUP BY DATEPART(YEAR, CalendarDate);
GO
SELECT *
FROM (VALUES('20130101',1000),
('20150501',755))V(YMD, Lapsed)
CROSS APPLY dbo.CountDays(V.YMD,V.Lapsed) CD;
一种方法是递归 CTE:
with dates as (
select v.d, 1000 - datediff(day, v.d, dateadd(year, 1, v.d)) as days
from (values (datefromparts(2013, 1, 1))) v(d)
union all
select dateadd(year, 1, d), days - datediff(day, d, dateadd(year, 1, d))
from dates
where days > 0
)
select d,
(case when days > 0 then datediff(day, d, dateadd(year, 1, d))
else datediff(day, d, dateadd(year, 1, d)) + days
end)
from dates;
Here 是一个 db<>fiddle.