В SQL как рассчитать количество дней в году на основе даты начала и количества прошедших дней - PullRequest
0 голосов
/ 23 мая 2019

Каким будет SQL для расчета количества дней в каждом году, если у меня была начальная дата и количество прошедших дней?

Например, дата (ymd) 2013-01-01 и прошедшие дни - 1000.

Я бы хотел, чтобы результат выглядел следующим образом

2013 = 365

2014 = 365

2015 = 270

Может ли это быть записано как функция типа datediff?

Я пытался использовать таблицу календаря, но, конечно, ссылка на это просто дает мне 2013 = 1000

Моя таблица календаря выглядит следующим образом.

DATE_ID  | DATE       | CALENDAR_YEAR | FINANCIAL_YEAR
-----------------------------------------------
20130101 | 2013-01-01 | 2013          | 2013/14

Это то, что я пробовал.

ВЫБРАТЬ

D.FISCAL_YEAR, SUM ([DAYS]) AS NUMBER_OF_DAYS

ОТ [dbo]. [ФАКТ] 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

Ответы [ 2 ]

0 голосов
/ 23 мая 2019

Один метод является рекурсивным 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;

Здесь - это скрипта db <>.

0 голосов
/ 23 мая 2019

Я бы лично составил таблицу подсчета для этого.Создав это, вы можете легко получать каждую дату и подсчитывать количество дней в каждом году:

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;
...