WTD this year compared to WTD last year - sql

I would like to determine the growth on sales data from current year WTD with sales data from the same week last year also WTD.
So if this week is Mon, Tue, Wed I am trying to compare Mon, Tue, wed from the same week last year to determine the sales growth. This needs to be dynamic in a sense since it will be running on a daily report, ending WTD on the previous day, through SSRS which will be emailed to various users.
I have done copious amounts of online searching and tried several iterations, all with undesirable affects.
The latest attempt being
SELECT
[storeid],
SUM([Sales]) as [2021SalesWTD]
FROM [dbo].[DailySales2021]
WHERE CONVERT(date, [date]) >= DATEADD(DAY, 1-DATEPART(dw, DATEADD(YEAR,-1,GETDATE())), CONVERT(date, DATEADD(YEAR,-1,GETDATE())))
AND DATEADD(DAY, 8-DATEPART(dw, DATEADD(YEAR,-1,GETDATE())), CONVERT(date, DATEADD(YEAR,-1,GETDATE())))
GROUP BY storeid
This returns the entire week

It might help you to try variable declarations.
Here's something I've drafted up:
--Get today's date, find the day of the week (1 indexed from Sunday) and subtract. Add 2 to balance this offset
DECLARE #MondayThisYear AS DATE = CAST(GETDATE()-DATEPART(WEEKDAY, GETDATE())+2 AS DATE)
--Get the date a year ago. I haven't checked for leap year, add it if you need it
DECLARE #DateLastYear AS DATE = #MondayThisYear-365
--Same idea as MondayThisYear, but using the date from last year
DECLARE #MondayLastYear AS DATE = CAST(#DateLastYear-DATEPART(WEEKDAY, #DateLastYear)+2 AS DATE)
--The number of days that have passed in this working week
DECLARE #WorkingDays AS INT = DATEDIFF(d, #MondayThisYear, GETDATE())
SELECT [insert columns]
FROM [insert table name]
WHERE ([date column]>#MondayThisYear AND [date column]<GETDATE()) OR
([date column]>#MondayLastYear AND [date column]<#MondayLastYear + #WorkingDays)
You might also need to check how I've defined the previous year's dates. In worst case you might get an off-by-one week error, but I don't think that's avoidable given the structure of the calendar.

Related

Need Last Month of Last Year Data

I am trying to write a query that looks at the last month and last month of last year data to compare. So since I am writing this in August of 2022 I want to see July of 2022 and July of 2021. I know I can run a between dates and have to update it every month but I want this to feed into PowerBi and be an automated report.
I can get last month's just fine the issue is last year last month. I have tried a couple of different queries and they either error out and fail or return nothing.
I am currently skipping the part for last month as I know it works. Can I please get some help with the last year part?
Declare #StartofCurrentMonth datetime
Set #StartofCurrentMonth = dateadd(month, DATEDIFF(MONTH,0,CURRENT_TIMESTAMP),0)
Select BranchID, ItemID, CAST(Ledgerdate AS Date) As 'LedgerDate', TransactionType
From ItemLedger
Where --LedgerDate >= DateAdd(Month, -1, #StartofCurrentMonth) AND LedgerDate < #StartofCurrentMonth OR
**Ledgerdate >= DATEADD(Year, -1, #startofcurrentMonth) AND LedgerDate <** **DATEADD(Month,-12,#startofCurrentMonth)**
AND TransactionType IN ('Item.Move', 'Item.Putaway')
Order By LedgerDate
Thank you
I figured it out finally.
I changed the last year stuff to:
Ledgerdate >= DATEADD(MONTH, -13, #startofcurrentMonth) AND LedgerDate < DATEADD(Month,-12,#startofCurrentMonth))
Thank you.

Generate custom start and end of months in SQL Server

I'm facing an issue while working with custom dates in T-SQL, we have a client that works with a different methodology of start and end of his month, instead of the default day 01 to start the month and ending in 31, 30 or 29, it's month start at day 26 and ends at 25 of the next month.
E.g., how usually is:
select sum(sales) as sales
from sales
where salesDate between '2020-09-01' and '2020-09-30'
-- or left(salesDate,7) = '2020-09'
Client custom month:
select sum(sales) as sales
from sales
where salesDate between '2020-08-26' and '2020-09-25' -- for setember
So, for this need, I have to calculate how many sales this client did from january until now, month per month, with this custom way... how can I do that?
Example of the query result I want to perform with this month determination:
This is a pretty awful situation. One method is to construct the first date of the month based on the rules:
select mon, sum(sales) as sales
from sales s cross apply
(values (case when day(salesdate) >= 26
then dateadd(month, 1, datefromparts(year(salesdate), month(salesdate), 1))
else datefromparts(year(salesdate), month(salesdate), 1)
) v(mon)
where v.mon >= '2020-01-01'
group by v.mon;
I would recommend adding the fiscal month column as a persisted computed column in the salesDate table so you can add an index and not have to worry about the computation.
Or, better yet, add a calendar table where you can look up the fiscal month for any (reasonable) date.

Find previous week/month/quarter number from current date

I would like to get last week, last month and last quarter numbers (appended with year number) based on current date.
I have used CONCAT and IIF to get current week/month/quarter numbers and substract it with -1, then check if it is last month/quarter to handle 0 values. Below is the code to get last month and quarter, however I am looking for an optimised code to make it work better. Also getting last week number using code similar to below will have issue with leap/non-leap years.
Last month:
SELECT CONCAT(YEAR(GETDATE()),IIF(DATEPART(MONTH,GETDATE())-1=0,12,DATEPART(MONTH,GETDATE())-1))
Last quarter:
SELECT CONCAT(YEAR(GETDATE()),IIF(DATEPART(QUARTER,GETDATE())-1=0,4,DATEPART(QUARTER,GETDATE())-1))
For example, If my current date is 4th Jan, 2019 -
Last week should return 52 or 53 (based on leap year), Last month should return 12, Last quarter should return 4.
--a week ago
select DATEADD(WEEK, -1, GETUTCDATE())
--the week number(of year), a week ago
select DATEPART(WEEK, DATEADD(WEEK, -1, GETUTCDATE()))
--a month ago
select DATEADD(MONTH, -1, GETUTCDATE())
--the month number, a month ago
select DATEPART(MONTH, DATEADD(MONTH, -1, GETUTCDATE()))
--a quarter ago
select DATEADD(QUARTER, -1, GETUTCDATE())
--the quarter number, a quarter ago
select DATEPART(QUARTER, DATEADD(QUARTER, -1, GETUTCDATE()))
General formula is thus:
Day and time, some PERIOD (week, month, quarter, year etc) ago:
DATEADD(PERIOD_IDENTIFIER, -NUMBER_OF_PERIODS, CURRENT_DATE)
The period that it was then:
DATEPART(PERIOD_IDENTIFIER, DATEADD(PERIOD_IDENTIFIER, -NUMBER_OF_PERIODS, CURRENT_DATE))
ps; every year has 53 weeks, not just leap years, because 365/7 is fractionally over 52
pps; I've used GetUtcDate above because I typically work in UTC as most of my tasks are on multi-country systems and all times are UTC. If you're specifically after something that reports "last X" for your local timezone you might need to use GetDate() instead so that the concept of "this week" and "last week" etc is aligned with your local concept of midnight/day changing
Use this in SQL Server.
select datepart(mm,getdate()-30) as Last_Month
,datepart(qq, getdate()-7) as Last_Quarter
,datepart(wk,getdate()-7) as Last_Week

Calculating Billing Weeks based on billing week date

Given the following dates:
Start Date: 09/17/2015
End Date 04/01/2016
I am attempting to calculate the total number of weeks and the billing weeks per month, billing weeks to date, and forecasted billing weeks.
Since our billing is only done by week to avoid prorating, this is a little difficult.
I.e,
The total number of weeks would be 29 using the following:
(select ceiling(convert(float,DATEDIFF(day,'09/17/2015','04/01/2016')+1)/7))
More over if I were to run this report on 8th of Jan 2016,
It should give me 1 week as the billing weeks billed to date, with the remaining 4 weeks as a forecast.
I was thinking of creating a couple of fields:
WeekStart and WeekEnd as dates fields, Month and Year field. And then to filter by dates where end date < today's date. Then aggregate that by the current month.
Example:
Weekstart: 09/17/2015
Weekend: 09/23/2015
Month: September
Year: 2015
Weekstart: 09/24/2015
Weekend: 09/30/2015
Month: September
Year: 2015
......
......
......
Weekstart: 03/31/2016
Weekend: 04/06/2016
Year: 2016
Month: March
Does this sound logical?
How can I go about creating this stored procedure. Any starting point would be very helpful.
Here is the quick sample Stored Proc I have created:
Here is the following sample I created, this should would I believe:
DECLARE #startdate datetime = '09/17/2015'
DECLARE #enddate datetime = '04/01/2016'
WHILE (#startdate <= #enddate)
BEGIN
Print CONVERT(VARCHAR, #startdate, 120) + '-----'+ CONVERT(VARCHAR, DateAdd(DD,+6,#startdate), 120)
set #startdate = DateAdd(DD,+6,#startdate)+1 ;
END

SQL Server 2005, Calculating upcoming birthdays from date of birth

This one has bugged me for a while now. Recently when revisiting some code I wrote for a customer a few years ago I was wondering if there is a more elegant solution to the problem.
The customer stores all of their clients information including date of birth (date time field)
They run an extract every Monday that retrieves any customer whose birthday will fall within the following week.
I.e. if the extract was run on Monday Jan 1st, Customers whose birthday fell between (and including) Monday Jan 8th -> Sunday Jan 14th would be retrieved.
My solution was to use the Datepart(dy) function and calculate all upcoming birthdays based off the customers date of birth converted to day of year, adding some logic to include for the extract being run at the end of a year.
The problem was that using Day of year throws results off by 1 day if the customer was born on a leap year and / or the extract is run on a leap-year after the 29th of Feb, so once again I had to add more logic so the procedure returned the expected results.
This seemed quite over-kill for what should be a simple task
For simplicity let’s say the table 'customer' contains 4 fields, first name, last name, dob, and address.
Any suggestions on how to simplify this would really be appreciated
Wes
Would something like this work for you?
select * from Customers c
where dateadd(year, 1900-year(dob), dob)
between dateadd(year, 1900-year(getdate()), getdate())
and dateadd(year, 1900-year(getdate()), getdate())+7
Why not use DATEPART(wk) on this year's birthday?
SET DATEFIRST 1 -- Set first day of week to monday
SELECT * FROM customer
WHERE DATEPART(wk, DATEADD(yy, DATEPART(yy, GETDATE()) - DATEPART(yy, customer.dob), customer.dob)) = DATEPART(wk, GETDATE()) + 1
It selects all customers who's birthday's weeknumber is one greater than the current weeknumber.
I think DATEADD should do the proper thing.
YEAR(GETDATE() - dbo.Patients.Dob) - 1900
I can safely assume you will never have customers born before 1900
Please Try This one.
SELECT TOP 10 BirthDate, FirstName
FROM Customers
WHERE DATEPART(mm,BirthDate) >= DATEPART(mm,GETDATE())
AND DATEPART(day,BirthDate) >= DATEPART(day,getdate())
OR DATEPART(mm,BirthDate) > DATEPART(mm,getdate())
ORDER BY DatePart(mm,BirthDate),DatePart(day,BirthDate)
this query will get upcoming birthdays including today itself