Calculate Fiscal Year - tsql

I am generating a case statement that will be a master shared dataset for our report date ranges since we frequently use the same date ranges. Currently I have previous week, previous month, previous year, current week, current month and current year. I would like to add our fiscal year which is (10/1 to 9/30) as well but I haven't been able to come up with a pure SQL way to do it.
DECLARE #frequency as nvarchar(20);
SET #frequency = 'CURRENT MONTH'
SELECT
CASE #frequency
WHEN 'PREVIOUS MONTH' THEN CONVERT(DATE,DATEADD(m,DATEDIFF(m,0,GETDATE())-1,0))
WHEN 'CURRENT MONTH' THEN CONVERT(DATE,DATEADD(dd, 0, DATEDIFF(dd, 0, DATEADD(dd,-(DAY(GETDATE())-1),GETDATE()))))
WHEN 'CURRENT WEEK' THEN CONVERT(DATE,DATEADD(dd, 1, DATEDIFF(dd, 0,DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATETIME)))))
WHEN 'PREVIOUS WEEK' THEN CONVERT(DATE,DATEADD(dd, -6, DATEDIFF(dd, 0,DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATETIME)))))
WHEN 'CURRENT YEAR' THEN CONVERT(DATE, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0))
WHEN 'PREVIOUS YEAR' THEN CONVERT(DATE, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) - 1, 0))
END as [START DATE],
CASE #frequency
WHEN 'PREVIOUS MONTH' THEN CONVERT(DATE,DATEADD(dd, 0, DATEDIFF(dd, 0,DATEADD(ms,-2,DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)))))
WHEN 'CURRENT MONTH' THEN CONVERT(DATE,DATEADD(D, -1, DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) + 1, '19000101')))
WHEN 'CURRENT WEEK' THEN CONVERT(DATE,DATEADD(dd, 1, DATEDIFF(dd, 0,DATEADD(DAY, 7 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATETIME)))))
WHEN 'PREVIOUS WEEK' THEN CONVERT(DATE,DATEADD(dd, -6, DATEDIFF(dd, 0,DATEADD(DAY, 7 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATETIME)))))
WHEN 'CURRENT YEAR' THEN CONVERT(DATE, DATEADD(ms, -2, DATEADD(YEAR, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) + 1, 0))))
WHEN 'PREVIOUS YEAR' THEN CONVERT(DATE, DATEADD(ms, -2, DATEADD(YEAR, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0))))
END as [END DATE]

I've found the simplest way to perform this logic is to shift your date by the offset. If 10/1/2018 belongs to FY 2018, subtract the 9 months to convert the date to 1/1/2018. Then get the year value.
YEAR(DATEADD(MONTH,-9,'2018-09-01')) = 2017
YEAR(DATEADD(MONTH,-9,'2019-09-01')) = 2018
YEAR(DATEADD(MONTH,-9,[YourDateField]))
With this, you can also calculate the Fiscal Month
MONTH(DATEADD( month, -9, '2018-09-01 )) = 12
My company use the Year the FY ends, so 10/1/2018 would be part of the FY closing 2019. For my arrangement, I would need to add 3 months instead of subtract to get the calculation to come out right.
This approach leverages date math exclusively so should be able to use an index in most situations.
To find the given day for the datepart you're looking for, try this:
SELECT CurrentWeek = DATEADD( WEEK, DATEDIFF( WEEK, '2018-01-01', GETDATE()), '2018-01-01' ),
CurrentMonth = DATEADD( MONTH, DATEDIFF( MONTH, '2018-01-01', GETDATE()), '2018-01-01' ),
CurrentYear = DATEADD( YEAR, DATEDIFF( YEAR, '2018-01-01', GETDATE()), '2018-01-01' )
;
By basing the calculation on a seed date, you don't need to truncate the smaller time values.

According to your calculations, this will work:
DECLARE #frequency as nvarchar(20);
SET #frequency = 'FINANCIAL YEAR'
SELECT
CASE #frequency
WHEN 'FINANCIAL YEAR' THEN CONVERT(date, DATEADD(month, -1,
DATEADD(year, -1, DATEADD(month, -8, DATEADD(month, 13-MONTH(GETDATE()),
DATEDIFF(month, 0, GETDATE()), 0))))))
END as [START DATE],
CASE #frequency
WHEN 'FINANCIAL YEAR' THEN CONVERT(date, DATEADD(ms, -2,
DATEADD(month, -8, DATEADD(month, 13-MONTH(GETDATE()), DATEADD(month,
DATEDIFF(month, 0, GETDATE()), 0)))))
END as [END DATE];
Play with the -8 in order to change the financial year - e.g. if the finacial year if from 2017-03 to 2018-03, then it will be -9.
I hope that's helpful!
P.S. I used April (from 2017-04 to 2018-04) as financial year

Related

T-SQL Retrieve Last 6 Weeks Data to the Previous Saturday

SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= DATEADD(ww, -6, (Select MAX([TradingDate]) From FactSalesDetail))
ORDER BY TradingDate
Can anyone advise how I can convert the above WHERE Clause from retrieving the last 6 weeks data from Max Date in my Fact Table to the last 6 weeks to the Previous Saturday?
So as of Today that would Saturday 1st Jan and then back 6 weeks from that?
Using the current weekday can get you last Saturday.
And if you bring ##DATEFIRST into the equation then it won't depend on the DATEFIRST setting.
SELECT TOP 100 *
FROM FactSalesDetail
WHERE TradingDate >= CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())))
AND TradingDate <= CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))
ORDER BY TradingDate
Test snippet for date range
SET DATEFIRST 7;
SELECT
datename(weekday, date_now) AS weekday_now, date_now
, datename(weekday, date1) AS wd1, date1
, datename(weekday, date2) AS wd2, date2
FROM
(
SELECT
CAST(GETDATE() AS DATE) AS date_now
, CONVERT(DATE, DATEADD(WEEK, -6, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE()))) AS date1
, CONVERT(DATE, DATEADD(DAY, -(##DATEFIRST+DATEPART(WEEKDAY,GETDATE()))%7,
GETDATE())) AS date2
) q
weekday_now
date_now
wd1
date1
wd2
date2
Tuesday
2022-01-04
Saturday
2021-11-20
Saturday
2022-01-01
db<>fiddle here

Error comparing the output of datepart to an integer

I have a query that i have been tinkering with to use as a source for a report.
For some odd reason when i try to compare the output of datepart(dw,GetDate()) to an integer (2 for Monday) it gives me an error telling me incorrect syntax. i then started looking into why i couldn't compare two integers in an iif statement and... i have found absolutely no answers.
here is the full code (i went back and forth on how to do this, this is this iterations attempt)
DECLARE #dp integer,#d integer
set #dp =DATEpart(dw,GETDATE())
set #d = 2
SELECT TOP 100 PERCENT CUST_ORDER_LINE.PRODUCT_CODE
,CUSTOMER_ORDER.ID
,CUSTOMER_ORDER.CUSTOMER_ID
,CUST_ORDER_LINE.PART_ID
,CUST_ORDER_LINE.MISC_REFERENCE
,CUST_ORDER_LINE.COMMODITY_CODE
,CUSTOMER_ORDER.SALESREP_ID
,CUSTOMER_ORDER.TERRITORY
,CUST_ORDER_LINE.ORDER_QTY * CUST_ORDER_LINE.UNIT_PRICE AS Amount
,CUSTOMER_ORDER.ORDER_DATE
FROM CUST_ORDER_LINE
INNER JOIN CUSTOMER_ORDER ON CUST_ORDER_LINE.CUST_ORDER_ID = CUSTOMER_ORDER.ID
WHERE (
iif(#dp = #d,CUSTOMER_ORDER.ORDER_DATE BETWEEN ( dateadd(day, datediff(day, 0, getdate()), 0) - 3) AND ( dateadd(day, datediff(day, 0, getdate()),0))),
CUSTOMER_ORDER.ORDER_DATE BETWEEN ( dateadd(day, datediff(day, 0, getdate()), 0) - 1)) AND ( dateadd(day, datediff(day, 0, getdate()), + 1))))
)
ORDER BY CUSTOMER_ORDER.ORDER_DATE DESC
The point of this query is to pull data from yesterday, and Friday if it is Monday.
EDIT: error code Msg 170, Level 15, State 1, Line 19
Line 19: Incorrect syntax near '='.
IIF is in 2012. You can try using CASE instead.
DECLARE #dp integer,#d integer
set #dp =DATEpart(dw,GETDATE())
set #d = 2
SELECT TOP 100 PERCENT CUST_ORDER_LINE.PRODUCT_CODE
,CUSTOMER_ORDER.ID
,CUSTOMER_ORDER.CUSTOMER_ID
,CUST_ORDER_LINE.PART_ID
,CUST_ORDER_LINE.MISC_REFERENCE
,CUST_ORDER_LINE.COMMODITY_CODE
,CUSTOMER_ORDER.SALESREP_ID
,CUSTOMER_ORDER.TERRITORY
,CUST_ORDER_LINE.ORDER_QTY * CUST_ORDER_LINE.UNIT_PRICE AS Amount
,CUSTOMER_ORDER.ORDER_DATE
FROM CUST_ORDER_LINE
INNER JOIN CUSTOMER_ORDER ON CUST_ORDER_LINE.CUST_ORDER_ID = CUSTOMER_ORDER.ID
WHERE
CUSTOMER_ORDER.ORDER_DATE BETWEEN CASE
WHEN #dp = #d THEN ( dateadd(day, datediff(day, 0, getdate()), 0) - 3)
ELSE ( dateadd(day, datediff(day, 0, getdate()), 0) - 1)
END
AND CASE
WHEN #dp = #d THEN ( dateadd(day, datediff(day, 0, getdate()),0))
ELSE ( dateadd(day, datediff(day, 0, getdate()), + 1))
END
ORDER BY CUSTOMER_ORDER.ORDER_DATE DESC

Build the calendar table for current year including weeknum divided to semester

for the below query i need divide the semesters starting from 1 to 26 .. first semester as 1 to 26 weeks and first semester should start from again 1 to 26
Any help is greating appreciated
DECLARE #StartDate DATETIME
DECLARE #CutoffDate DATETIME
SET #StartDate = Dateadd(yy, Datediff(yy, 0, Getdate()), 0)
SET #CutoffDate = Dateadd(yy, Datediff(yy, 0, Getdate()) + 1, -1)
SELECT day,
[week nu],
semester,
[semester week nu]
INTO #currentdates
FROM (SELECT Day = Dateadd(day, rn - 1, #StartDate),
Datepart(week, Dateadd(day, rn - 1, #StartDate)) [Week nu],
CASE
WHEN Month(Dateadd(day, rn - 1, #StartDate)) <= 6 THEN
'First Semester'
ELSE 'Second Semester'
END AS Semester,
Datepart(week, Dateadd(day, rn - 1, #StartDate)) AS
[Semester Week nu]
FROM (SELECT TOP (Datediff(day, #StartDate, #CutoffDate)) rn =
Row_number()
OVER (
ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]) AS x) AS y;
I've got a couple of changes, first, you need to add 1 to your last datediff, your last date was December 30, not 31!
Second of all, I just get the date and week number in the first subselect, and then use these ine case statements for the select
The semester number is if week nu<=26,
The semester week nu is week nu if week nu<=26 else wwek nu -26
DECLARE #StartDate datetime DECLARE #CutoffDate datetime
SET #StartDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
SET #CutoffDate = DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) + 1, -1)
SELECT DAY,
[Week nu],
case when [Week nu]<=26 then 'First Semester' Else 'Second Semester' end Semester,
case when [Week nu]<=26 then [Week nu] Else [Week nu]-26 end[Semester Week nu]
INTO #currentDates
FROM
(SELECT DAY = DATEADD(DAY, rn - 1, #StartDate),
DATEPART(WEEK,DATEADD(DAY, rn - 1, #StartDate)) [Week nu]
FROM
(SELECT TOP (DATEDIFF(DAY, #StartDate, #CutoffDate)+1) rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.[object_id]) AS x) AS y;

SQL Server 2012: Round to NEAREST(!) start of month (in timestamp format) from a timestamp column)

I need to round to NEAREST start of month (in timestamp format) from a timestamp column.
How do one accomplish this?
Examples:
TimestampColumn A: Rounded to these values
2012-01-07 18:18:29.923 2012-01-01 00:00:00.000
2012-01-14 12:58:13.122 2012-01-01 00:00:00.000
2012-06-09 17:10:30.787 2012-06-01 00:00:00.000
2012-05-31 09:29:43.870 2012-06-01 00:00:00.000
2012-10-22 12:09:47.067 2012-11-01 00:00:00.000
2012-10-15 04:35:11.013 2012-10-01 00:00:00.000
Consider converting to date first
DECLARE #d DATETIME
set #d = CONVERT(DATE, '2012-02-14 12:58:13.122')
SET #d = DATEADD(DAY, 1-datepart(day, #d), #d)
SELECT #d
Here is one way to do it - just subtract all the parts of the date which you don't care about:
DECLARE #d DATETIME
set #d = '2012-02-14 12:58:13.122'
SET #d = DATEADD(DAY, 1-datepart(day, #d), #d)
SET #d = DATEADD(hour, -datepart(hour, #d), #d)
SET #d = DATEADD(minute, -datepart(minute, #d), #d)
SET #d = DATEADD(second, -datepart(second, #d), #d)
SET #d = DATEADD(millisecond, -datepart(millisecond, #d), #d)
SELECT #d
Calculate the length of the applicable month in seconds and then decide whether you are past the middle of the month. Go forward or back as needed.
declare #Foo as DateTime = '2012-10-15 12:35:11.013'
select
DateAdd( month, DateDiff( m, 0, #Foo ), 0 ) as 'Year/Month',
DateDiff( s, DateAdd( month, DateDiff( m, 0, #Foo ), 0), #Foo ) as 'Seconds Into Month',
DateDiff( s, DateAdd( month, DateDiff( m, 0, #Foo ), 0 ), DateAdd( month, DateDiff( m, 0, #Foo ) + 1, 0 ) ) as 'Seconds In Month',
DateDiff( s, DateAdd( month, DateDiff( m, 0, #Foo ), 0 ), DateAdd( month, DateDiff( m, 0, #Foo ) + 1, 0 ) ) / 2 as 'Seconds In Half Month',
DateAdd( month, DateDiff( m, 0, #Foo ) + Round( 1.0 * DateDiff( s, DateAdd( month, DateDiff( m, 0, #Foo ), 0), #Foo ) / DateDiff( s, DateAdd( month, DateDiff( m, 0, #Foo ), 0 ), DateAdd( month, DateDiff( m, 0, #Foo ) + 1, 0 ) ), 0 ), 0 ) as 'Rounded Date'
Thanks for contributing. But I'm going for this one; its good enough.
SELECT CASE
WHEN DATEDIFF(DAY, GETDATE(), DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0)) >
ABS(DATEDIFF(DAY, GETDATE(), DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)))
THEN DATEADD(dd, datediff(dd, 0, DATEADD(DAY, DATEDIFF(DAY, GETDATE(), DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)), GETDATE() ) )+0, 0)
ELSE dateadd(dd, datediff(dd, 0, DATEADD(DAY, DATEDIFF(DAY, GETDATE(), DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0)), GETDATE() ) )+0, 0)
END
Here is an example. You have 5 fields: the date you want to convert, the converted date as you wanted, the first day of the month, the last day of the month, and the first day of the next month.
Just choose what you need in it:
SELECT
BED_Meeting_When,
CASE WHEN DAY(BED_Meeting_When) < 15 THEN (DATEADD(DAY, (-DAY(BED_Meeting_When) + 1), BED_Meeting_When)) ELSE DATEADD(DAY, (-DAY(BED_Meeting_When) + 1), DATEADD(MONTH, 1, BED_Meeting_When)) END,
DATEADD(DAY, (-DAY(BED_Meeting_When) + 1), BED_Meeting_When) AS 'Arrondi au premier du mois',
DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, BED_Meeting_When) + 1, 0)) AS 'Arrondi au dernier du mois',
DATEADD(DAY, (-DAY(BED_Meeting_When) + 1), DATEADD(MONTH, 1, BED_Meeting_When)) AS 'Arrondi au premier du mois suivant',
BEMR_Titre
FROM bpri_entretien_detail
INNER JOIN bpri_entretien_motif ON (BED_BEMR_Idx = BEMR_Idx)
Hi I know this is late to the party a little simple offering can never offend I hope
Creating a mini temp table I pop'd the dates offered in the original post
and then selected from it as below
create table #DT(
TS_A datetime, TS_B datetime)
insert into #DT (ts_a) values ('2012-01-07 18:18:29.923'),
('2012-01-14 12:58:13.122'),
('2012-06-09 17:10:30.787'),
('2012-05-31 09:29:43.870'),
('2012-10-22 12:09:47.067'),
('2012-10-15 04:35:11.013')
select TS_A, DATEADD(MONTH, DATEDIFF(MONTH, 0,ts_a), 0) TS_B from #DT
Results - I hope this is clear
RESULTS
Amazing how times they are a changing :-)
TX
I hope this turns out alright haven't posted any where for over a decade

tsql dynamic where

I'm struggling with this procedure.
If its Monday thru Thursday I want everything 90 days ahead;
SELECT
PR.ClientID
,PR.NewDealEndDate
INTO
#OriginalRenewalDetails
FROM
Shiva.dbo.ProductRemortgage PR WITH (NOLOCK)
LEFT JOIN Shiva.dbo.ClientLead AS CL WITH (NOLOCK)
ON CONVERT(VARCHAR(50), CL.OriginatorReferenceID) = CONVERT(VARCHAR(50), PR.ClientID)
WHERE -- 90 days from now.
PR.NewDealEndDate = DATEADD(dd, 90, DATEDIFF(dd, 00, GETDATE()))
AND CL.ClientID IS NULL
However if it is a Sunday I want the following changed in the Where clause. So that I get Friday and Saturdays results too.
WHERE -- 90 days from now.
PR.NewDealEndDate BETWEEN DATEADD(dd, 88, DATEDIFF(dd, 00, GETDATE())) AND DATEADD(dd, 90, DATEDIFF(dd, 00, GETDATE()))
AND CL.ClientID IS NULL
I can't find an efficient way of doing this. Any help appreciated.
Use IF.
pseudo:
if day = sunday
begin
select with 88
end
else
begin
select with 90
end
OR change the WHERE clauses to something like:
WHERE (PR.NewDealEndDate = DATEADD(dd, 90, DATEDIFF(dd, 00, GETDATE()))
AND CL.ClientID IS NULL AND Datepart(weekday, getdate()) <> 1)
OR
(PR.NewDealEndDate BETWEEN DATEADD(dd, 88, DATEDIFF(dd, 00, GETDATE()))
AND DATEADD(dd, 90, DATEDIFF(dd, 00, GETDATE()))
AND CL.ClientID IS NULL
AND Datepart(weekday, getdate()) = 1)
No need for dynamic SQL or two separate queries here. Replacing the **DAY = SUNDAY** part with whatever logic you're currently using to determine the day is Sunday:
WHERE PR.NewDealEndDate BETWEEN DATEADD(DAY,
CASE WHEN **DAY = SUNDAY** THEN 88 ELSE 90 END,
DATEDIFF(DAY, 0, GETDATE())) AND DATEADD(DAY, 90, DATEDIFF(dd, 0, GETDATE()))
AND CL.ClientID IS NULL;
You could also calculate the range beforehand, e.g.
DECLARE #start SMALLDATETIME, #end SMALLDATETIME;
SET #end = DATEADD(DAY, 90, DATEDIFF(DAY, 0, GETDATE()));
SET #start = CASE WHEN **DAY = SUNDAY** THEN DATEADD(DAY, -2, #end) ELSE #end END;
WHERE PR.NewDealEndDate BETWEEN #start END #end
AND CL.ClientID IS NULL;
You could do the following:
SELECT PR.ClientID
, PR.NewDealEndDate
INTO #OriginalRenewalDetails
FROM Shiva.dbo.ProductRemortgage PR WITH (NOLOCK)
LEFT JOIN Shiva.dbo.ClientLead AS CL WITH (NOLOCK)
ON CONVERT(VARCHAR(50), CL.OriginatorReferenceID) = CONVERT(VARCHAR(50), PR.ClientID)
WHERE CL.ClientID IS NULL
AND
(
(
PR.NewDealEndDate = DATEADD(dd, 90, DATEDIFF(dd, 00, GETDATE()))
AND Datepart(weekday, getdate()) <> 1 -- 1 is Sunday
)
OR
(
PR.NewDealEndDate BETWEEN DATEADD(dd, 88, DATEDIFF(dd, 00, GETDATE()))
AND DATEADD(dd, 90, DATEDIFF(dd, 00, GETDATE()))
AND Datepart(dayofweek, getdate()) = 1
)
)
declare #adjustment int--SELECT DATEPART(weekday, getdate())
set #adjustment =
CASE
WHEN DATEPART(weekday, getdate())
in (1,2,3,4,5) THEN 90
ELSE 88
END
WHERE
PR.NewDealEndDate BETWEEN DATEADD(dd, #adjustment...