2014-08-28 4 views
0

Возможно, я слишком задумываюсь об этом, но я немного в тупике.Возврат списка финансовых лет между диапазонами дат

Я пытаюсь суммировать данные по месяцам, по финансовому году, возвращая одну строку за финансовый год, со столбцом за каждый месяц.

Я могу вернуть одну колонку в месяц легко, однако стараюсь вернуть финансовые годы, поскольку строки доказывают трудную часть.

Моя теория когда у меня есть финансовый год, выбранный в качестве строки, я могу просто присоединиться к этому в подзапроса суммируется финансового года/месяца, давая мне 1 на 1.

Проблема в том, запускается финансовый год 1 августа. Диапазон дат запроса может варьироваться от 1 финансового года до диапазона дат, который может составлять 5 лет.

Например, если бы я имел диапазон дат 01/08/2013-31/07/2014, я бы хотел финансовый год, чтобы вернуться как:

2013/2014 

Если бы я имел диапазон дат 01/08/2012-31/07/2014, я хочу ниже вернулся как финансовый год:

2012/2013 
2013/2014 

Если бы я имел диапазон дат 01/01/2012-28/08/2014, я бы хотите, чтобы нижеследующие возвратили в качестве финансового года:

2011/2012 
2012/2013 
2013/2014 
2014/2015 

Это моя работа до сих пор, но она не работает должным образом.

DECLARE @DateFrom datetime, @DateTo datetime 
SET @DateFrom = '2011-08-01' 
set @DateTo = '2014-07-31' 


; with FinYr as 
     (
     select @DateFrom as AllDate, @DAteTo as EndDate, case when datepart(MONTH, @DateFrom) < 8 then convert(varchar(4),datepart(year, @DateFrom)-1)+'/'+convert(varchar(4),datepart(year, @DateFrom)) else convert(varchar(4),datepart(year, @DateFrom))+'/'+convert(varchar(4),datepart(year, @DateFrom)+1) End as FinYear 
     union all 
     select dateadd(year,1,AllDate) as AllDate, dateadd(year,1,EndDate) as EndDate,case when datepart(MONTH, dateadd(year,1,AllDate)) < 8 then convert(varchar(4),datepart(year, dateadd(year,1,AllDate))-1)+'/'+convert(varchar(4),datepart(year, dateadd(year,1,AllDate))) else convert(varchar(4),datepart(year, dateadd(year,1,AllDate)))+'/'+convert(varchar(4),datepart(year, dateadd(year,1,AllDate))+1) End as FinYear 
     from FinYr 
     where dateadd(year,-1,EndDate) <= convert(datetime,(convert(varchar(4),year(@Dateto))+'-07-31')) 
     ) 
select AllDate,EndDate, FinYear 
from FinYr 
+0

Вы можете разместить DDL и некоторые выборочные данные для FinYr? –

+0

FinYr - это не данные dbase, это рекурсивная функция. – OWSam

+0

О, доброе горе .... Мне нужно больше кофейного стата !!! –

ответ

1

Вы можете использовать таблицу подсчета голосов или цифр для чего-то подобного. В моем коде я создал таблицу таблиц «на лету». Это нулевой тип чтения ... супер быстрый.

DECLARE @DateFrom datetime, @DateTo datetime; 
SET @DateFrom = '2011-08-01'; 
set @DateTo = '2014-07-31'; 

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 

select CAST(N as CHAR(4)) + '/' + CAST(N + 1 as CHAR(4)) 
from cteTally 
where N >= DATEPART(YEAR, @DateFrom) 
and N <= DATEPART(YEAR, @DateTo); 

ОК с обновленными требованиями вы можете выполнить это с помощью небольшой настройки к вышеуказанному коду. Это должно привести вас туда.

select CAST(N as CHAR(4)) + '/' + CAST(N + 1 as CHAR(4)) 
from cteTally 
where N >= case when DATEPART(MONTH, @DateFrom) > 6 then DATEPART(YEAR, @DateFrom) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateFrom)) end 
and N <= case when DATEPART(MONTH, @DateTo) < 6 then DATEPART(YEAR, @DateTo) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateTo)) end 

Я думаю, что вижу, что я сделал не так там .... попробуйте это.

select CAST(N as CHAR(4)) + '/' + CAST(N + 1 as CHAR(4)) 
, case when DATEPART(MONTH, @DateTo) < 8 then DATEPART(YEAR, DATEADD(YEAR, -1, @DateTo)) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateTo)) end 
from cteTally 
where N >= case when DATEPART(MONTH, @DateFrom) > 6 then DATEPART(YEAR, @DateFrom) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateFrom)) end 
and N <= case when DATEPART(MONTH, @DateTo) < 8 then DATEPART(YEAR, DATEADD(YEAR, -1, @DateTo)) else DATEPART(YEAR, DATEADD(YEAR, 1, @DateTo)) end 
+0

Он производит именно то, что вы заявили, что хотите в качестве вывода. Что не так? Если вы сообщите мне, что не правильно, я могу это исправить. –

+0

Хммм кажется близким ... Если я задаю диапазон дат '2013-08-01' - '2014-08-20' Затем он возвращает 2013/2014 и 2014/2015, как и ожидалось. Если я ставлю в: «2013-08-01'-„2014-07-30“ Он по-прежнему возвращает 2013/2014 и 2014/2015, где в этом сценарии, он только должен reuturn 2013/2014 – OWSam

+0

Почему выход изменения? 1 июля ваши финансовые годы меняются? 1-е июля?Если дата переключения является переменной, вы должны использовать таблицу календаря. –

0

Я считаю, что это покажет список лет вы хотели:

DECLARE 
    @DateFrom datetime, 
    @DateTo datetime 
SET @DateFrom = '2011-01-01' 
SET @DateTo = '2014-07-31' 


SELECT CAST(YearList AS VARCHAR(4)) + '/' + CAST((YearList +1) AS VARCHAR(4)) AS FiscalYear 
FROM 
    (
    SELECT 
     DATEPART(YEAR, @DateFrom) - CASE WHEN DATEPART(MONTH, @DateFrom) >= 8 THEN 0 ELSE 1 END + 
     ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY (SELECT NULL)) -1 AS YearList 
    FROM sys.all_objects 
) q 
WHERE YearList <= DATEPART(YEAR, @DateTo) - CASE WHEN DATEPART(MONTH, @DateTo) >= 8 THEN 0 ELSE 1 END 
+0

Спасибо за ответ, но, как и с другим ответом, я получаю год слишком много. Выбор до 31/07/2014 должен возвращаться только в 2010/2011, 2011/2012, 2012/2013 и 2013/2014, так как 31/07/2014 - последний день финансового года 2013/2014. Я действительно получаю 2010/2011, 2011/2012, 2012/2013, 2013/2014 и 2014/2015 – OWSam

+0

Причина, по которой я использую cte для этого, заключается в том, что он дает вам некоторый контроль над значениями. sys.all_objects может быть таким маленьким числом, что может не иметь достаточно строк. –

+0

Извините @OWSam, мой браузер не вывел ваше сообщение, и я не получил его вовремя, чтобы поработать над ним. Я редактировал, независимо от того, что это стоит. Шон, я думал то же самое в отношении CTE, но учитывая как отсутствие спецификаций RDBMS в OP, так и, вероятно, низкое количество финансовых лет, реально возвращаемых, пошел просто. – AHiggins

Смежные вопросы