Следующее представление базы данных усекает дату к финансовому году (1-го апреля):
CREATE OR REPLACE VIEW FISCAL_YEAR_VW AS
SELECT
CASE
WHEN to_number(to_char(SYSDATE, 'MM')) < 4 THEN
to_date('1-APR-'||to_char(add_months(SYSDATE, -12), 'YYYY'), 'dd-MON-yyyy')
ELSE
to_date('1-APR-'||to_char(SYSDATE, 'YYYY'), 'dd-MON-yyyy')
END AS fiscal_year
FROM
dual;
Это позволяет нам вычислять текущий финансовый год на основе сегодняшней даты.
Как это вычисление может быть упрощено или оптимизировано?
Возможно, это ...
SELECT to_date('01/04/' ||
to_char(extract(YEAR FROM SYSDATE)
- CASE WHEN extract(MONTH FROM SYSDATE) BETWEEN 1 AND 4 THEN 1 ELSE 0 END),
'DD/MM/YYYY') FROM dual;
Думаю, это еще один вариант ...
SELECT add_months(trunc(SYSDATE) - extract(DAY FROM SYSDATE) + 1,
- (extract(MONTH FROM SYSDATE) + CASE
WHEN extract(MONTH FROM SYSDATE) <= 4 THEN 12 ELSE 0 END) + 4)
FROM dual;
Другие варианты переписываются как функция, которая возвращает дату, или логику можно было бы упростить, если бы вы могли просто вернуть номер года для текущий финансовый год, поскольку вам понадобится только логика в to_char.
TRUNC () может применяться к датам с разными масками формата. Наиболее уместно trunc (sysdate, 'yyyy')
дает нам первый день года. Таким образом, мы получим 01 апреля текущего года ...
add_months(trunc(sysdate, 'yyyy'), 3)
и эту дату за предыдущий год ...
add_months(trunc(add_months(sysdate, -12), 'yyyy'), 3)
Итак:
CREATE OR REPLACE VIEW FISCAL_YEAR_VW AS
WITH cte as
( select add_months(trunc(sysdate, 'yyyy'), 3) as this_year
, add_months(trunc(add_months(sysdate, -12), 'yyyy'), 3) as last_year
from dual )
SELECT
CASE
WHEN SYSDATE >= cte.this_year THEN
cte.this_year
ELSE
cte.last_year
END AS fiscal_year
FROM
cte;
предостережение: у меня не было возможности проверить это кода еще нет, поэтому он может содержать опечатки. Позже протестирую и при необходимости поправлю.
Я считаю, что функция Oracle TO_CHAR (дата, 'Q') очень полезна для расчета финансовых календарей. В приведенном ниже запросе с помощью предложения with создается две вещи
Пример:
with test_dates as (
select sysdate + level * 80 test_date from dual connect by level < 11
),
fiscal_map as (
select 1 cal, 2 fiscal from dual
union
select 2 cal, 3 fiscal from dual
union
select 3 cal, 4 fiscal from dual
union
select 4 cal, 1 fiscal from dual
)
select
test_date,
TO_CHAR(test_date, 'Q') cal_quarter,
fiscal_map.fiscal,
(case when CAL < fiscal then
TO_CHAR(test_date, 'yyyy') + 0
else TO_CHAR(test_date, 'yyyy') + 1
end) FISCAL_YEAR
from test_dates, fiscal_map
where fiscal_map.cal = TO_CHAR(test_date, 'Q')
order by test_date
Вывод:
TEST_DT CAL_Q FISCAL Q FISCAL_YR
22-Jul-10 3 4 2010
10-Oct-10 4 1 2011
29-Dec-10 4 1 2011
19-Mar-11 1 2 2011
07-Jun-11 2 3 2011
26-Aug-11 3 4 2011
14-Nov-11 4 1 2012
02-Feb-12 1 2 2012
22-Apr-12 2 3 2012
11-Jul-12 3 4 2012