Applying filter to sum quarterly data - sql-server

I would like some help with the filter for summing Quarterly data.
For Yearly data I have added the formula.
For Quarterly data, I have hard coded for now but need to get the system to calculate.
So for example next quarter which will be Quarter 3, I need to calculate figures for current year/current quarter (summing figures for 3 months in that quarter)
SNIPPET of filter code
WHERE [Status] = 'Complete'
AND (YEAR([datefield]) = YEAR(GETDATE()) - 1
OR YEAR([datefield]) = YEAR(GETDATE()) - 2
OR YEAR([datefield]) = YEAR(GETDATE())
AND MONTH([datefield]) IN(4, 5, 6)) --Apr/May/June.

Sorry for providing an incomplete answer. I have thought of this after I've answered.
SELECT *
FROM table
WHERE [Status] = 'Complete'
AND [datefield] BETWEEN CONVERT(date, DATEADD(M, -2, DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE())))
AND EOMONTH(DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE()))
Explanation:
For the filter to be accurate, you need to get the first day and last day of the month.
First Day:
Get current date:
SELECT GETDATE()
2018-09-06 17:03:35.467
Get current date minus 1
SELECT DATEADD(D, -1, GETDATE())
2018-09-05 17:03:35.467
Subtract "current date minus 1" (the above result) to the current date.
SELECT DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE())
2018-09-01 17:03:35.467
Get date part only:
SELECT CONVERT(date, DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE()))
2018-09-01
Last Day:
Same as getting the first day, but changing CONVERT to EOMONTH since the latter already returns the result as date part only
SELECT EOMONTH(DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE()))
2018-09-30
So you now have
SELECT CONVERT(date, DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE()))
,EOMONTH(DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE()))
2018-09-01
2018-09-30
Get the previous 2 months from the current month.
SELECT CONVERT(date, DATEADD(M, -2, DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE())))
Notice that I just added DATEADD(M, -2, ) to the First Day value.
Combine the first day of 2 months ago and the last day of the current month you get
SELECT CONVERT(date, DATEADD(M, -2, DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE())))
,EOMONTH(DATEADD(D, -DAY(DATEADD(D, -1, GETDATE())), GETDATE()))
2018-07-01
2018-09-30

Related

How can i get dates Saturday to Friday using SQL getdate()

How can I get use gatedate() to always pick up the last Saturday to current Friday.
When I try to use the code I getting a static Saturday date
I have tried this way
Select
cast dateadd(y,datediff(y,0,getdate()),-1 ) as date) as Satuday,
cast(dateadd(d,-3,dateadd(week,datediff( week,0,getdate()),0)) as Friday
example
Saturday date = 31/12/2023
Friday date = 6/01/2022
Try the following code, you can adjust the code...
SELECT DATEADD(DD, 12, DATEADD(ww, DATEDIFF(ww, 0, DATEADD(dd, -6, CURRENT_TIMESTAMP)) -1, 0)) -- Saturday
SELECT DATEADD(DD, 18, DATEADD(ww, DATEDIFF(ww, 0, DATEADD(dd, -6, CURRENT_TIMESTAMP)) -1, 0)) -- Friday

Truncating date + time using DateTime2

I have been using this format for years to truncate dates and times
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, '1980-02-05 12:45'), 0) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, 0, '1980-02-05 12:45'), 0) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, 0, '1980-02-05 12:45'), 0) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, 0, '1980-02-05 12:45'), 0) AS Year;
But I have a need to store very early dates like 1400-01-01 and therefore I can use DateTime2.
But how would I support the ability to still truncate like above using DateTime2?
Changing the year above to 1400 from 1980 will then result in
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, '1400-02-05 12:45'), 0) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, 0, '1400-02-05 12:45'), 0) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, 0, '1400-02-05 12:45'), 0) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, 0, '1400-02-05 12:45'), 0) AS Year;
The conversion of a varchar data type to a datetime data type resulted
in an out-of-range value.
SO casting to DateTime2
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, CAST('1400-02-05 12:45' AS DATETIME2)),0) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, 0, CAST('1400-02-05 12:45' AS DATETIME2)),0) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, 0, CAST('1400-02-05 12:45' AS DATETIME2)), 0) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, 0, CAST('1400-02-05 12:45' AS DATETIME2)), 0) AS Year;
The conversion of a datetime2 data type to a datetime data type
resulted in an out-of-range value.
I am assuming that the 0 is being treated as a DateTime data type and effectly casting it to DateTime.
Trying to cast the 0 to DateTime2 using CAST(0 AS DATETIME2) gives me this error
Explicit conversion from data type int to datetime2 is not allowed.
In the end I am wanting to use these as persisted columns in a table which worked fine with DateTime data types but not so easy with DateTime2
You should use some specific base date instead of 0. 0 can be implicitly converted into datetime type. For datetime2 such implicit conversion is not allowed. In addition, the base date should have a datetime2 type. Then DATEDIFF and DATEADD would work with datetime2 values.
Another reason for using explicit base date is that you need this base date to be the first day of the year and to have 00:00:00 time for the formula to work correctly. Implicit starting dates, like 0 converted to datetime or '' converted to datetime2 also have these properties right now, but do you really want to rely on internal details of the type implementation? It is better to spell out such things explicitly and it makes the formula easier to understand for a new person.
Besides, if you ever want to truncate to the week boundary using the same approach, then you'd have to pick a base date that is Monday (if your week starts on Monday) or Sunday (if your week starts on Sunday). The formula remains the same, but base date is important.
Example 1 - works
DECLARE #VarBase datetime2 = '2000-01-01';
DECLARE #VarValue datetime2 = '1400-02-05 12:45';
SELECT
DATEADD(HOUR, DATEDIFF(HOUR, #VarBase, #VarValue), #VarBase) AS Hour,
DATEADD(DAY, DATEDIFF(DAY, #VarBase, #VarValue), #VarBase) AS Day,
DATEADD(MONTH, DATEDIFF(MONTH, #VarBase, #VarValue), #VarBase) AS Month,
DATEADD(YEAR, DATEDIFF(YEAR, #VarBase, #VarValue), #VarBase) AS Year;
Example 2 - works
SELECT
DATEADD(HOUR, DATEDIFF(HOUR, #VarBase, '1400-02-05 12:45'), #VarBase) AS Hour,
DATEADD(DAY, DATEDIFF(DAY, #VarBase, '1400-02-05 12:45'), #VarBase) AS Day,
DATEADD(MONTH, DATEDIFF(MONTH, #VarBase, '1400-02-05 12:45'), #VarBase) AS Month,
DATEADD(YEAR, DATEDIFF(YEAR, #VarBase, '1400-02-05 12:45'), #VarBase) AS Year;
Example 3 - doesn't work
SELECT
DATEADD(HOUR, DATEDIFF(HOUR, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Hour,
DATEADD(DAY, DATEDIFF(DAY, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Day,
DATEADD(MONTH, DATEDIFF(MONTH, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Month,
DATEADD(YEAR, DATEDIFF(YEAR, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Year;
Adding a value to a 'datetime' column caused an overflow.
It doesn't work, because literal 2000-01-01 is converted into datetime, not datetime2.
Example 4 - works
SELECT
DATEADD(HOUR, DATEDIFF(HOUR, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Hour,
DATEADD(DAY, DATEDIFF(DAY, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Day,
DATEADD(MONTH, DATEDIFF(MONTH, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Month,
DATEADD(YEAR, DATEDIFF(YEAR, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Year;
Try to use:
DECLARE #Default DATETIME2 = CAST('' AS DATETIME2)
SELECT DATEADD(HOUR, DATEDIFF(HOUR, #Default, CAST('1400-02-05 12:45' AS DATETIME2)), #Default) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, #Default, CAST('1400-02-05 12:45' AS DATETIME2)), #Default) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, #Default, CAST('1400-02-05 12:45' AS DATETIME2)), #Default) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, #Default, CAST('1400-02-05 12:45' AS DATETIME2)), #Default) AS Year;
I found that instead of using CAST ('DateTimeData' as DateTime2) if I use Convert it can be a deterministic result.
As documented on this post: Cannot persist computed column - not deterministic
ALTER TABLE dbo.QuakeRawJSON
ADD [Date] AS (DATEADD(DAY,DATEDIFF(DAY, CONVERT(DATETIME2,'',112)
,origintime),CONVERT(DATETIME2,'',112))) PERSISTED;
Thanks for your help.

MS Sql Date format?

I'm pretty new to MSSQL and was wondering if someone could help me convert the following where statement from looking at previous week to previous month.
ks.report_date BETWEEN (convert(varchar(113), (DATEADD(day, (-1 * DATEPART(dw, (dateadd(week, -1, getdate())))) + 1, (dateadd(week, -1, getdate())))), 101))
AND (convert(varchar(113), (DATEADD(day, (-1 * DATEPART(dw, (dateadd(week, -1, getdate())))) + 7, (dateadd(week, -1, getdate())))), 101))
SQL Server has a function called EOMonth() that will take a date and give you the end of the month containing that date. You can then use DATEADD to subtract months from that value to get the last day of previous months. Lastly, use DATEADD again to add 1 day to get the first day of the month. Here is an example.
BETWEEN DATEADD(DAY, 1, DATEADD(MONTH, -2, EOMONTH(GETDATE())))
AND DATEADD(MONTH, -1, EOMONTH(GETDATE()))
If you're using an earlier version than SQL Server 2012 then this would work:
BETWEEN DATEADD(MONTH, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
AND DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))

tSQL select previous 3 months

Im not a sql person and have been thrust into being one :\
Im trying to get the previous 3 months of data without the current month.
WHERE DATEPART(m, start_date) = DATEPART(m, DATEADD(m, -3, getdate()))
and DATEPART(yyyy, start_date) = DATEPART(yyyy, DATEADD(m, -3, getdate()))
this gets me the data from January only, i need Jan-Mar.
WHERE start_date >= dateadd(mm,datediff(mm,0,getdate())-3,0)
and this gets me everything from jan 1st - now.
So now im stuck and not sure what to do.
mssql ver: 2012
Thank you in advance for any help.
WHERE DateColumn >= DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE()) -3,0)
AND DateColumn < DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE()) ,0)
This will return the data from Between 2015-01-01 and 2015-03-31
You can try this:
Where datediff(mm, start_date, getdate()) in (1, 2, 3)
Does this helps?:
WHERE start_date BETWEEN DATEADD(m, -3, getdate()) AND DATEADD(m, -1, getdate())
You can use something like this:
WHERE MONTH(start_date)>= MONTH(getdate())- 3 AND MONTH(start_date)< MONTH(getdate())
You can build a string and convert it to a date... such as:
WHERE start_date >= dateadd(month,-3, convert(datetime,convert(varchar(10),Month(GETDATE())) + '/01/' + convert(varchar(10),Year(GETDATE()))))
and start_date < convert(datetime,convert(varchar(10),Month(GETDATE())) + '/01/' + convert(varchar(10),Year(GETDATE())))
SELECT DATEADD(MONTH,DATEDIFF(MONTH,0,DATEADD(MONTH,-3,GETDATE())),0) -- FIRST DAY OF MONTH, THREE MONTHS AGO
,DATEADD(MILLISECOND,-3,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) -- LAST DAY OF LAST MONTH

Deterministic scalar function to get week of year for a date

Here is a great way of how to get day of week for a date, Deterministic scalar function to get day of week for a date.
Now, could anyone help me to create a deterministic scalar function to get week of year for a date please? Thanks.
This works deterministically, I can use it as a computed column.
datediff(week, dateadd(year, datediff(year, 0, #DateValue), 0), #DateValue) + 1
Test code:
;
with
Dates(DateValue) as
(
select cast('2000-01-01' as date)
union all
select dateadd(day, 1, DateValue) from Dates where DateValue < '2050-01-01'
)
select
year(DateValue) * 10000 + month(DateValue) * 100 + day(DateValue) as DateKey, DateValue,
datediff(day, dateadd(week, datediff(week, 0, DateValue), 0), DateValue) + 2 as DayOfWeek,
datediff(week, dateadd(month, datediff(month, 0, DateValue), 0), DateValue) + 1 as WeekOfMonth,
datediff(week, dateadd(year, datediff(year, 0, DateValue), 0), DateValue) + 1 as WeekOfYear
from Dates option (maxrecursion 0)

Resources