SQL Help - Summarize Customer Fiscal Year By Quarters - sql

I've been at this question for a bit and I'm currently stuck:
This is my current attempt:
I only took an image of a small portion of the code since the general idea can be understood within the few case statements. It's turning out to be way too messy and I think theirs an easier way to go about it. An answer isn't necessarily needed but some guidance would help since I'd like to try it out for myself. Thank you!

are you still struggling with this one?
Create function fiscalYearSummary (#OrderDate Date, #StartFiscalYearFromGivenMonth int)
returns nvarchar(20)as
begin
declare #MonthOfYear int
declare #Quarter int
set #MonthOfYear = datepart(MONTH, #OrderDate)
set #Quarter = (((((#MonthOfYear - (#StartFiscalYearFromGivenMonth )) + 12) % 12) + 1) / 4) + 1
return case #Quarter when 1 then 'Quarter I' when 2 then 'Quarter II' when 3 then 'Quarter III' when 4 then 'Quarter IV' else 'Error' end
end
This would be used in a select
select dbo.fiscalYearSummary('20190101',1) -- January with the first month of the fiscal year January.
select dbo.fiscalYearSummary('20190401',4) -- April with the first month of the fiscal year April.
select dbo.fiscalYearSummary('20191231',1) -- December with the first month of the fiscal year January
I'm sure it can be done better, but this should get you started.
I get the Month from the passed in date (1 to 12)
Subtract #StartFiscalYearFromGivenMonth to drag it back by that many months.
Add 12 (a year) to make it positive, mod it with 12 to get it in the range 0 to 11, then add 1 to make that 1 to 12.
I divide the result by 4 to get the quarter - 0 to 3, then add 1 again, into range 1 to 4.
then a simple case returns the quarter.
I hope this helps

Related

Find number of days in a given week according to the month for a given date. in SQL

Consider the date "2022-07-02"
For the month July first week only have 3 days in it.
I need to find the number of days in the week for the given date.
In above date the week has 3 days where "2022-07-02" day reside.
Example 2 :
For month June in 2022 first week has 5 days in the week
Therefore if i declare a date as "2022-06-03" it should pass the number of days in the week as 5
I need a query to find the number of days for the specific week.
set datefirst 1 -- assumes Monday is set as start of week
declare #myDate date = getdate();
-- calculate the next last day of week
declare #nextSunday date = dateadd(day, 7 - datepart(weekday, #myDate), #myDate);
select case
-- advancing into the next month implies a partial week
-- datediff(month, #myDate, nextSunday) = 1 would be equivalent
when day(#nextSunday) < day(#myDate) then 7 - day(#nextSunday)
-- else see if still within first week
when day(#nextSunday) < 7 then day(#nextSunday)
else 7 end;
Within a query you might use it this way:
select case
when day(nextSunday) < day(dateColumn) then 7 - day(nextSunday)
when day(nextSunday) < 7 then day(nextSunday)
else 7 end
from
myData cross apply (
values (dateadd(day, 7 - datepart(weekday, dateColumn), dateColumn))
) v(nextSunday);
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=ee5bfb52dabe31dd619cfd136689db59
If you don't want the shorthand form then just replace every instance of nextSunday in the final step with its full expression.
There's nothing in the logic that prevents this from working with another first day of week. I just chose a variable name that helped ellucidate this particular problem.

SSRS. Workday Function

I'm trying to convert the below Excel formula into SSRS but having looked around I cannot seem to find a solution. I can calculate the number of working days between two dates but what I'm trying to do is add on a number of working days to a date. Essentially I don't have the 2nd date.
I guess it would be something along the lines of the DATEADD function?
=WORKDAY($A1,B$1)
Hope someone can help
Many thanks
Here is a tsql solution to add X Business Days to a date.
declare #calendar as table (theDate date, dayOfWeek varchar (10));
declare #startDate as date = '20170704';
declare #businessDaysToAdd as integer = 10;
insert into #calendar
select theDate
, datename(dw, theDate) dow
from
dbo.dateTable('20170701', '20170720') ;
with temp as (
select theDate
, dayOfWeek
, rank() over (order by theDate) theRank
from #calendar
where theDate > #startDate
and dayOfWeek not in ('Saturday', 'Sunday')
)
select * from temp
where theRank = #businessDaysToAdd;
Notes
dbo.DateTable is a table valued function that just happens to exist in the database I was using. In real life, you might have an actual calendar table of some sort.
This example does not include holidays.
This is only the start of the answer to the posted question. It only solves the problem of Essentially I don't have the 2nd date.
Type this into the expression for the textbox. (From SSRS 2008 Datediff for Working Days)
=(DateDiff(DateInterval.day,Parameters!STARTDATE.Value,Parameters!ENDDATE.Value)+1)
-(DateDiff(DateInterval.WeekOfYear,Parameters!STARTDATE.Value,Parameters!ENDDATE.Value)*2)
-(iif(Weekday(Parameters!STARTDATE.Value) = 7,1,0)
-(iif(Weekday(Parameters!ENDDATE.Value) = 6,1,0))-1)
Ok after much perseverance I managed to get what I wanted in both TSQL and SSRS. My objective was to measure Agent productivity so I didn’t want to count the weekend and this would be unfair. If a date fell on a weekend then I wanted it to jump to a Monday. Likewise if adding number of days onto a date went over a weekend in the future then I needed the incremented date to reflect this. For the end user (In SSRS) I wanted a leading edge (Like an Upside down triangle) so that if the date + number working days was in the future then set to NULL, showing a zero would look like no productivity which is incorrect.
First TSQL - My base query started with the following SO thread but after trying many of the options I was finding when the date fell on a Saturday or Sunday the solution did not work for me (I was unable to create functions due to permissions). However tweaking the below got me there and I dealt with Sunday specifically
Add business days to date in SQL without loops
SELECT
,DATEADD(WEEKDAY, (/*Your Working Days*//5)*7+(/*Your Working Days*/ % 5) +
(CASE WHEN DATEPART(WEEKDAY,/*Your Date*/) <>7 AND DATEPART(WEEKDAY,/*Your Date*/) + (/*Your Working Days*/ % 5) >5 THEN 2
WHEN DATEPART(WEEKDAY,/*Your Date*/) = 7 AND DATEPART(WEEKDAY,/*Your Date*/) + (/*Your Working Days*/ % 5) >5 THEN 1 ELSE 0 END), /*Your Date*/) AS [IncrementedDate]
FROM /*YourTable*/
Then for SSRS - The 2 key points here is that TSQL will divide as an integer if the source number is an integer so this needs to be handled in SSRS and secondly you need to set the first week day to Monday as part of the expression.
I put this expression into a Matrix with Date Created being my Row Group and Contact Working Days being my Column Group.
=DATEADD("W",(INT(ReportItems!ContactWorkingDays.Value/5))*7+(ReportItems!ContactWorkingDays.Value MOD 5) + IIF(DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) <> 7 AND (DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) + (ReportItems!ContactWorkingDays.Value MOD 5) >5),2,IIF(DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) = 7 AND (DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) + (ReportItems!ContactWorkingDays.Value MOD 5) >5),1,0)),ReportItems!DateCreated.Value)
This does not include holidays - I'm not too bothered at this stage and that is for a rainy day! :)

Select Date Between Just Day and Month Excluding Year

The following is the pseudo code for what I want to do:
When Date is Between 04-01 and 03-31 of the following year then output as Q1.
I know how to do this with the year but not excluding the year.
I have no idea what you mean by output "Q1". However, if you want your years to start on April 1st (which seems like a reasonable interpretation of what you are sking), the easiest way is to subtract a number of days. For most years you will deal with, you can do:
select year(dateadd(day, - (31 + 28 + 31), date) as theyear
Of course, this only works three years out of four, because of leap years. One way to fix this is with explicit logic -- but that gets messy. Another way is to add the remaining months and subtract one year:
select year(dateadd(day, (30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31), date) - 1 as theyear
It's unclear exactly what you're trying to do. Q1 usually indicates a quarter, a three-month period. A quarter running from 1 April to 31 March of the following year isn't much of a quarter :)
However, assuming you're trying to select stuff within a certain span of time starting from a particular date, you might try a little date/time arithmetic. First, a few notes:
datetime values have a nominal precision of 1 millisecond (and an actual precision of approximately 3ms). That means that something like '31 March 2014 23:59:59.999' is rounded up to '1 April 2014 00:00:00.000'. The largest time value for a given day is `23:59:59.997'. This can have...deleterious effects on your queries if you're not cognizant of it. Don't ask me how I know this.
datetime literals without a time component, such as '1 April 2013', are interpreted as start-of-day ('1 April 2014 00:00:00.000').
So, something like this:
declare
#dtFrom datetime ,
#dtThru datetime
set #dtFrom = '1 April 2013'
set #dtThru = dateAdd(year,1,dtFrom)
select *
from foo t
where t.someDateTimeValue >= #dtFrom
and t.someDateTimevalue < #dtThru
should probably do you.
You might want to adjust the setting of #dtThru to suit your requirements: if you're actually looking for the end of a quarter, you migh change it to something like
set #dtThru = dateAdd(month,3,dtFrom)
If you have a fiscal year that runs from 1 April through 31 March and want to figure out, say, what fiscal year and quarter your data represents, you might do something like this:
select FiscalYear = datepart(year,t.someDateTimeValue)
- case datepart(month,t.someDateTimeValue) / 4
when 0 then 1 -- jan/feb/mar is quarter 4 of the prev FY
else 0 -- everything else is this FY
end ,
FiscalQuarter = case datepart(month,t.someDateTimevalue) / 4
when 0 then 4 -- jan/feb/mar is Q4 of the prev FY
when 1 then 1 -- apr/may/jun is Q1 of the curr FY
when 2 then 2 -- jul/aug/sep is Q2 of the curr FY
when 3 then 3 -- oct/nov/dec is Q3 of the curr FY
end ,
*
from foo t
I think what you want is the following:
SELECT year(dateadd(q, -1, mydate)) AS yearEndingQ1
FROM mytable
This would give the year as 2014 for all dates between 04/01/2014 and 03/31/2015. Of course it's possible you want a result of 2015 instead in which case you want:
SELECT year(dateadd(q, 3, mydate)) AS yearEndingQ1
FROM mytable
Hope this helps.
UPDATE per OP's comment: "I am tracking data for a year ending Quarter x. Our fiscal year is a bit weird around here. So basically it would be fiscal year ending Q1, fiscal year ending Q2, etc. Perhaps I could have provided more clarity in my question."
This would give results in three separate columns for fiscal year ending Q1, fiscal year ending Q2, and fiscal year ending Q3. (I assume you don't need anything for fiscal year ending Q4!!)
SELECT year(dateadd(q, -1, mydate)) AS yearEndingQ1
, year(dateadd(q, -2, mydate)) AS yearEndingQ2
, year(dateadd(q, -3, mydate)) AS yearEndingQ3
FROM mytable

Rolling 6 Months

I have 2 parameters in my report, Month and Year.
I also have a table which in one column has the count of rows for that particular month and another column which has the count of rows for that specific month and the next 5 months (Rolling 6 month).
Both of these columns have an expression which links to the parameters as shown below:
Month Expression:
6 Month Expression:
My parameters use specific values which i have put in (1 - 12) so when my rolling month adds 1 value each time as you can probably guess this wont work when I come near the latter months of the year as my expression does not roll over to next year and just stops at December.
Overview: Parameters are integer values 1 - 12 and I am not sure how to calculate a rolling 6 months which will carry over to the next year when selecting months late in the year. e.g. If I select November as my Month parameter, my rolling 6 months will only display the sum of rows for November and December, not going to the next year. I am assuming this is because my month values are integers and in my expression I add numbers to the integers for each month therefore my rolling 6 will be trying to add months 11, 12, 13, 14, 15, 16 when obviously months only go to 12.
This is not an answer to your question, but looking at this, you may be able to find a solution with SQL itself.
See the query below. Consider this as your report source sql.
DECLARE #A TABLE (ID INT IDENTITY(1,1),DT DATE)
INSERT INTO #A (DT)
VALUES
('2013-01-26'),('2013-02-23'),('2013-03-20'),
('2013-04-23'),('2013-05-23'),('2013-07-23'),
('2013-08-23'),('2013-08-29'),('2013-09-23'),
('2013-12-10'),('2014-03-01')
If you join the result with itself, some what like below, you will get the result in sql query itself, you need to only show it in report. See below.
SELECT DATEPART(YEAR,DT) [Y],DATEPART(MONTH,DT) [M],COUNT(*) [ROLLING 6]
FROM (
SELECT A.*
FROM #A A,#A B
WHERE ((DATEPART(YEAR,B.DT) * 12) + DATEPART(MONTH,B.DT)) BETWEEN
(DATEPART(YEAR,A.DT) * 12) + DATEPART(MONTH,A.DT) AND
((DATEPART(YEAR,A.DT) * 12) + DATEPART(MONTH,A.DT) + 6)) LU
GROUP BY DATEPART(YEAR,DT),DATEPART(MONTH,DT)
ORDER BY [Y],[M]

How to get every Monday out of a Date

I need some help to understand a certain line in a code. The code takes the turnovers of every Monday in the year 2010 and at the last line in summarizes all the turnovers to one.
Here is the code:
SELECT
CASE
WHEN GROUPING (DATUM) = 1 THEN 'Gesamtumsatz'
ELSE CAST (DATUM AS VARCHAR (40))
END AS MONTAGSDATEN,
AVG (VERKAUFSWERT * VERKAUFSMENGE) as UMSATZ
FROM Data_Star_Awesome.dbo.VERKAUFSFAKTEN vk
INNER JOIN DIMDATUM dimD on vk.DATUMID=dimD.DATUMID
WHERE DATEDIFF(dd,0, DATUM)%7=0
AND JAHR = 2010
GROUP BY ROLLUP (DATUM)
The problematic line I don't understand is the following:
WHERE DATEDIFF(dd,0, DATUM)%7=0
What I know is that it takes the days out of the date variable but I don't get the %7=0 part. The DATEDIFF function should give back all the days. Are these days saved in the % the placeholder? And how does it get all the Mondays by using the 7=0?
It would be great if someone could help me out.
Thanks a lot :)
Modulo or % operator is the same as in a lot of programming languages. It returns the remainder after the division.
The DATEDIFF function takes two dates and returns the difference in a specified datepart, which in your query is the days represented by dd.
Also 0 as date converts to 1/1/1900 which happens to be a Monday. So your query is calculating the days between 1/1/1900 and the DATUM field in days and if its Mod is 0 then DATUM is Monday.
You could simply say:
datename(weekday,<datetime-value>)
Which will return 'Monday', 'Tuesday', 'Wednesday', etc. The problem with this approach is that the returned value is localized. If the SQL server's language is changed, your test for 'Monday' will fail.
This expression will always work:
( ##datefirst + ( datepart(weekday,today) - 1 ) ) % 7
It evaluates to 1-7, where Monday is always 1 and Sunday is always 7, regardless of culture/language settings or the current value of ##datefirst, as set by set datefirst.
We can then convert this into this discriminant function, yielding 1 or 0 to indicate whether or not the date is Monday:
case ( ##datefirst + ( datepart(weekday,today) - 1 ) ) % 7 when 1 then 1 else 0 end