Find startdate of a week from last year in SSRS - sql-server

We assume that the week starts from Mon and ends at Sunday.
While trying to comparing with last year, how can we get the right dates?
For example, if i want to compare this week (10/23/2017 to 10/29/2017) with year same week (10/24/2016 to 10/30/2016)
I am setting 2 parameters in SSRS BeginDate and BeginDateLastYear . The value of BeginDate = 10/23/2017
How can i assume the value for BeginDateLastYear as a value precisely to the Monday of same week number in last year ( IN this case it should be 10/24/2016) ?
Currently i am trying to set the value of StartDate in last year like
BeginDateLastYear =DATEADD(DateInterval.Year,-1,Parameters!BeginDate.Value)
Also i tried to use
=DATEADD(DateInterval.Week,-52,Parameters!BeginDate.Value) , but not very sure will this work precisely to same week start date of last year

In reporting services you can use the following expression for BeginDateLastYear
= DATEADD(
DateInterval.WeekOfYear,
IIF(
DATEPART(DateInterval.WeekOfYear,DATEADD(DateInterval.WeekOfYear, -52 , Parameters!BeginDate.Value))<> DATEPART(DateInterval.WeekOfYear, Parameters!BeginDate.Value) ,
-53,
-52
) ,
Parameters!BeginDate.Value
)
Code logic:
If by going back 52 weeks the two week numbers do not match go back 53 weeks, else go back 52 weeks
In case you want to implement it in SQL without using the second parameter (SSRS has some issues on cascading parameters)
SET #BeginDateLastYear =
DATEADD(
wk,
CASE WHEN DATEPART(wk,DATEADD(wk, -52 , #BeginDate))<> DATEPART(wk,#BeginDate)
THEN -53
ELSE -52 END,
#BeginDate
)

Related

unable to understand the dateadd function in SQL

I have a SQL query like
SET THIS_YEAR_END = '2022-11-01';
SET THIS_YEAR_START = DATEADD(DAY, -4*7+1, $THIS_YEAR_END);
SET LAST_YEAR_END = '2021-11-02';
SET LAST_YEAR_START = DATEADD(DAY, -4*7+1, $LAST_YEAR_END);
select end_date from (
select * from data
where DATE>= DATEADD(DAY, -27 * 7, $LAST_YEAR_START))
AND END_DATE BETWEEN CUST.END_DATE - 26 * 7 AND CUST.END_DATE - 7
I'm confused with this dateadd function in SQL. Can anyone please explain what exactly it's doing?
Here is the docs: https://docs.snowflake.com/en/sql-reference/functions/dateadd.html
Basically DATEADD is adding a specified value to a certain date. The first parameter is indicating the units of time that you want to add (e.g. DAY or MONTH), the second parameter specifies the number of units (e.g. number of days or number of months) and the third paramter is the date, to which you want to add something.
In your example in line 2 you are reducing THIS_YEAR_END by -4*7+1 (=-27) days.

question regarding oracle sysdate to last month date

OBSERVED_DATE BETWEEN add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1))
I need to run query between the 01-11-2019 to 30-11-2019 how do I change the sysdate to last month values
Assuming your dates may have non-zero time of day, it is best to write such conditions with explicit inequalities, rather than using between. Between is inclusive of both ends, when what you need (in almost all cases) is >= 1 November and < 1 December.
If, instead, you write <= 30 November (which is what you do when you use between the way you are trying now), you will miss everything from the last day of the month, 30 November, that has a time-of-day greater than midnight.
The where clause should look like this:
...
where observed_date >= add_months(trunc(sysdate, 'mm'), -1)
and observed_date < trunc(sysdate, 'mm')
Still, if you insist on getting the last day of the previous month (such as 30 November) for whatever reason, that is simply
trunc(sysdate, 'mm') - 1
(that is, subtract one day from the first day of the current month).
There is another function which returns last day of the month. I.e. last_day
So your condition should look like this:
where observed_date
between add_months(trunc(sysdate, 'mm'), -1)
and last_day(add_months(sysdate, -1))
Cheers!!

Compare two dates and get difference in exact days, months, years, and more SQL Server 2008 R2

I am comparing two dates in SQL Server and need following information in precise manner:
Input:
Start Date = 12/28/2015
End Date = 12/25/2020
Result returned (each piece in different column):
Days = 1825 (includes start/end date in calculation)
Years = 4
Months = 11
Days = 28
How many days in Start Month = 31 days (Because it is December)
Occupancy in Start Month = (because December has 31 days, it would be 4/31) = .12903225806
How many days in End Month = 31 days (Because it is December)
Occupancy in End Month = (because December has 31 days, it would be 25/31) = .8064516129
For 1-3, you can check https://www.w3schools.com/sql/func_sqlserver_datediff.asp. It's fairly simple, you can just use datediff and specify the unit of interest.
For 4, you can simply do day(Start Date) to get the date.
For 5 and 7, you can use:
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#myDate)+1,0)
to get the end of month date of the given date and use day() to get the day part of the datetime object.
For 6 and 8, it's just simple math, you get number of month in that month from 5 and 7, and then, if Start Date, then (day(eom(Start Date)) - day(Start Date) + 1) / day(eom(date) and if End Date, then day(End Date) / day(eom(End Date)).
I didn't give you the full code as I don't have SQL server running besides me. Hope it helps.

Is Date between 1st of 1st Month and 29th of 7th month of any year (Sql Server 2008+)

I need to check if a Date is between 1st of 1st month and 29th of 7th month of any year.
Before going ahead and hacking extracting Month Day from the date and comparing it to being between 0101 and 0729 (or just checking if the date dd mm is less than 629) type of hideousity solution, I must ask is there a function to check wether any date falls in between particalr days and month , invariant of the it's year.
Other wise extracting months and days from the date and doing some hacky arithmatic is easy, but I want to be leave a better code for the poor programmer who will come after me and not having to guess why the hell some freaky made up arithmatic is going on, I rather be explicit even if it takes longer.
Another option:
DECLARE #TheDate date = '2016-07-29';
SELECT 1
WHERE DATEADD(Year, -(YEAR(#TheDate) - 2000), #TheDate)
BETWEEN '2000-01-01' AND '2000-07-29'
where datetimeField < dateFromParts( year( dateTimeField ), 7, 30)
EDIT: Above would work in 2012 and later. For 2008 you could do some arithmetic which is "very simple" for a developer:
where datetimeField < CAST(CAST(year(dateTimeField) AS CHAR(4))+'0730' AS DATE);
Or simplified a bit:
where datetimeField < CAST(year(dateTimeField) AS CHAR(4))+'0730';
PS: A common pitfall in using BETWEEN (which acts like x >= v1 and x <= v2) on a datetime field, where the field might have time part, is not suggested and would never help to precisely get the correct records (because there is no way to specify the ending time). Instead you should always use x >= v1 and x < v2 style where v2 is the minimum exclusive upper value. ie: To get all the sales in May 2000 (saleDate has time component):
saleDate >= '20000501' and saleDate < '20000601'
NOT:
saleDate between '20000501' and '20000531'
OR NOT:
saleDate >= '20000501' and saleDate <= '20000531'
Select * from TableWithNoName where DateField1 between DATETIMEFROMPARTS( YEAR(DateField1),1, 1, 0, 0, 0, 0 ) and DATETIMEFROMPARTS( YEAR(DateField1),7, 29, 23, 59, 59, 999 )
assuming DateField1 is a Date Value

Utilizing SQL datepart to indentify consecutive periods of time

I have a stored procedure that works correctly, but don't understand the theory behind why it works. I'm indentifying a consecutive period of time by utilizing a datepart and dense rank (found solution through help elsewhere).
select
c.bom
,h.x
,h.z
,datepart(year, c.bom) * 12 + datepart(month, c.bom) -- this is returning a integer value for the year and month, allowing us to increment the number by one for each month
- dense_rank() over ( partition by h.x order by datepart(year, c.bom) * 12 + datepart(month, c.bom)) as grp -- this row does a dense rank and subtracts out the integer date and rank so that consecutive months (ie consecutive integers) are grouped as the same integer
from
#c c
inner join test.vw_info_h h
on h.effective_date <= c.bom
and (h.expiration_date is null or h.expiration_date > c.bom)
I understand in theory what is happening with the grouping functionality.
How does multiplying year * 12 + month work? Why do we multiply the year? What is happening in the backend?
The year component of a date is an integer value. Since there are 12 months in a year, multiplying the year value by 12 provides the total number of months that have passed to get to the first of that year.
Here's an example. Take the date February 11, 2012 (20120211 in CCYYMMDD format)
2012 * 12 = 24144 months from the start of time itself.
24144 + 2 months (february) = 24146.
Multiplying the year value by the number of months in a year allows you to establish month-related offsets without having to do any coding to handle the edge cases between the end of one year and the start of another. For example:
11/2011 -> 24143
12/2011 -> 24144
01/2012 -> 24145
02/2012 -> 24146

Resources