in mssql get first, second, third weekdate of current month, what date would it be the next month - sql-server-2016

Given a date lets say Aug 2, 2019 which is first friday of the month. what would be the first friday of next month (sept 6th). Now lets say I have sept 26th which is the last thur of the month. what date would it be for the last thur of next month. I have to do this in MSSQL.

What would you do for the option of September 12th? Sounds like you have two separate scenarios.
In either case, I would use a Date Table or Calendar Table if you have one. If not, set one up. I highly recommend it. Ed Pollock does a great article on what a date table setup would look like here: Designing a Calendar Table. SQLServer.Info has a good example of the table here: Table Example. Second example for good measure Table Setup
Table Setup. This is how it should look. Or at least something similar. You can add more columns to do more comparisons.
Once you have your calendar table set up, its a matter of comparing the date you want to the table.
This is how you can grab the first week of the next month based on a date table
DECLARE #Date DATE = '8/2/2019';
SELECT [dt].Date
FROM [Datetbl] AS [dt]
WHERE [dt].[Weekday] = DATEPART([weekday], DATEADD(day, -1, #Date)) -- is same day of the week
AND [dt].Month = DATEPART(month, DATEADD(MONTH, 1, #Date)) -- Grab the month number for "Next Month"
AND [dt].Year = DATEPART(year, DATEADD(MONTH, 1, #Date)) -- Grab year of next month since that will be different for December
AND [dt].[WeekOfMonth] IN
(SELECT MIN([WeekOfMonth])
FROM [Datetbl] AS [dt1]
WHERE [dt1].[Weekday] = DATEPART([weekday], DATEADD(day, -1, #Date))
AND [dt1].Month = DATEPART(month, DATEADD(MONTH, 1, #Date))
AND [dt1].Year = DATEPART(year, DATEADD(MONTH, 1, #Date))
); -- returns Sept 6
This is how you would go about getting the last weekday of the month based on a date table
DECLARE #Date DATE = '9/26/2019';
SELECT [dt].Date
FROM [Datetbl] AS [dt]
WHERE [dt].[Weekday] = DATEPART([weekday], DATEADD(day, -1, #Date)) -- is same day of the week
AND [dt].Month = DATEPART(month, DATEADD(MONTH, 1, #Date)) -- Grab the month number for "Next Month"
AND [dt].Year = DATEPART(year, DATEADD(MONTH, 1, #Date)) -- Grab year of next month since that will be different for December
AND [dt].[WeekOfMonth] IN
(SELECT MAX([WeekOfMonth])
FROM [Datetbl] AS [dt1]
WHERE [dt1].[Weekday] = DATEPART([weekday], DATEADD(day, -1, #Date))
AND [dt1].Month = DATEPART(month, DATEADD(MONTH, 1, #Date))
AND [dt1].Year = DATEPART(year, DATEADD(MONTH, 1, #Date))
); -- returns Oct 31st
Hope this helps.

Related

How to find the date of the same day ( same week ) for the previous year ? ( SQL)

I have a table that contains dates , For each date I need to return a reference date: same day of the same number of the week but during the previous year.
For example let's suppose today is 03-03-2023 , the day is friday and the number of the week is 5 I want as a resulat the date of friday in 2022 during the week number 5.
I have tried this formula but it didn't give me a good result
SELECT DATEADD(day, (DATEPART(week, #now) * 7 + DATEPART(weekday, #now)) - (DATEPART(week, DATEADD(year, -1, #now)) * 7 + DATEPART(weekday, DATEADD(year, -1, #now))), DATEADD(year, -1, #now))
enter image description here
Any help will be appreciated.
Best regards,
Try this:
SELECT DATEADD(WEEK, -52, CAST(GETDATE() AS DATE))
If you can use the ISO weeks definition, you can try the following.
CASE
WHEN YEAR(DATEADD(week, -52, #Date)) = YEAR(#Date)
THEN DATEADD(week, -52, #Date)
ELSE DATEADD(week, -53, #Date)
END
For about 80% of the cases, the -52 calculation will yield the correct result, otherwise (with one exception noted below) -53 gives the correct answer.
The only exceptional case is when the reference date is in ISO week 53 and the prior year only has 52 weeks. in that case, it will end up in week 52 of the prior year, which may be a reasonable accommodation.
If you wish to use a different week definition I believe the above can be adapted to week instead of iso_week and possibly use SET DATEFIRST to adjust the week boundaries.
If you don't care about ISO weeks or any other week-numbering scheme, and just want to get the closest date one year-ago on having the same day-of-week, then Nayanish's posted is the simple answer. If you also want to always guarantee that year is offset by 1, then the following adjustment can be made:
CASE
WHEN DATEPART(year, DATEADD(week, -52, #Date)) < DATEPART(year, #Date)
THEN DATEADD(week, -52, #Date)
ELSE DATEADD(week, -53, #Date)
END

How to filter my results so it shows the last four months of data - sql

I'm trying to create a stored procedure that gets the last 4 months worth of results from the below query but I'm unsure how to do this.
This is what I have done so far:
Declare #Number varchar(30) = '12'
Select
month = month(EndDate),
YEAR = YEAR(EndDate),
SUM(DownloadUnits) as downloads,
SUM(UploadUnits) as uploads,
number
from testTable
where number=#Number
GROUP BY MONTH(EndDate), Year(Enddate),number
How can I filter it out so that when I pass month parameter (I haven't created it yet) it filters out the results so it only shows the last four months? (I have hard coded the number parameter for testing)
The last N months from now meet the condition
where EndDate >= dateadd(month, -#DEDUCT_MONTHS, cast(getdate() as DATE))
Removing the cast will enforce the current time as a constraint as opposed to midnight N months ago.
If you need to get whole months then you will need to get the first of the month 4 months ago.
You can get the first of the current month using:
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101');
Adapting this slightly will give you the first of the month 4 months ago:
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) - 4, '19000101');
Then you can just apply this filter to your query:
WHERE EndDate >= DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) - 4, '19000101')
Or if you need to pass the number of months a parameter (it should be an INT not a varchar by the way):
WHERE EndDate >= DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) - #Number, '19000101')
If you pass a date parameter, just replace GETDATE() with your parameter name.
DECLARE #StartDate date
SET #StartDate=Dateadd(Month, Datediff(Month, 0, DATEADD(m, -6, getdate())), 0)
--first day of the month, (current month-6 month)
The script above will return with the first day of the month - 6 month ago .
This solution is from stackoverflow somewhere, unfortunately I dont seem to find the original post.. :(
To understand how it works try to reverse-engineer as per follows:
DECLARE #StartDate1 date
SET #StartDate1= DATEADD(m, -6, getdate())
PRINT #Startdate1
DECLARE #StartDate2 int
SET #StartDate2= Datediff(Month, 0, DATEADD(m, -6, getdate()))
PRINT #Startdate2
DECLARE #StartDate3 date
SET #StartDate3=Dateadd(Month, 1369, 0)
PRINT #Startdate3

How to Find Current Month and Year From Custom Date range?

I have a problem about custom date range. let me explain it, for our company month count from current month day 21 to next month day 20. if i want to know which employee join current month then normally i can find using sql
SELECT *
FROM tblEmployeeMaster
--CURRENT MONTH
WHERE MONTH(DateOfJoining)=MONTH(GETDATE()) AND YEAR(DateOfJoining)=YEAR(GETDATE())
but for this custom date range i can not find employee who are join in this month. For example in this system if i want to find list of employee joined in this month then result will be show that employee who join in previous month after day 21 to current month day 20. Could someone please help me?
In this example, this month's period is considered to be from 21 of the previous month to 20 of current month, employees in that period are considered to be this month's employees (all who came to company after 2012-05-21 until 2012-06-20 (including 2012-06-20)). Try it:
SELECT DateOfJoining,
DATEADD(DAY, 20, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0)) PeriodStart,
DATEADD(DAY, 19, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) PeriodEnd
FROM tblEmployeeMaster
WHERE DateOfJoining > DATEADD(DAY, 20, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0))
AND
DateOfJoining < DATEADD(DAY, 20, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
SELECT *
FROM tblEmployeeMaster
WHERE DateOfJoining BETWEEN CAST(CAST(YEAR(GETDATE()) AS VARCHAR) +'-'+ CAST(MONTH(GETDATE()) AS VARCHAR) +'-21' AS DATETIME)
AND CAST(CAST(YEAR(DATEADD(month,1,GETDATE())) AS VARCHAR) +'-'+ CAST(MONTH(DATEADD(month,1,GETDATE())) AS VARCHAR) +'-20' AS DATETIME)

SQL Date Function

I may be using the wrong term (hence why I can't find it on google).
"Are there any functions or common code for Accounting Months Deliminations?"
For Example, this month started on a friday but on most accounting journals the weeks are measured by the first monday of the month so instead of having the 1st of July it would be the 4th of July. Same thing with the month end (29th instead of the 31st)
Again, I'm sure someone has created this 'wheel' before, and I can't seem to find it for the life of me.
The following query assumes a table, SalesTable, has a field called Amount (the value you want to sum) and a field called SaleDate (the date on which the sale occured.) It also assumes that accounting months begin the first Monday of the month and end on the Sunday prior to the beginning of the next accounting month.
Again, I highly recommend a table-based approach to this, but if you can't modify the schema, this should do the trick in T-SQL:
SELECT
CASE WHEN s.SaleDate < DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
THEN DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, DATEADD(day,-7,s.SaleDate) ),DATEADD(day,-7,s.SaleDate) )), 0)
ELSE DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
END AccountingMonth,
SUM(s.Amount) TotalSales
FROM SalesTable s
GROUP BY
CASE WHEN s.SaleDate < DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
THEN DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, DATEADD(day,-7,s.SaleDate) ),DATEADD(day,-7,s.SaleDate) )), 0)
ELSE DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
END
Note that the AccountingMonth return field actually contains the date of the first Monday of the month. In actual practice, you probably want to wrap this entire query in another query that reformats AccountingMonth to whatever you like... "2011-07", "2011-08", etc.
Here's how it works: This bit of code is the important part:
DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, 6 - DATEPART(DAY, s.SaleDate ),s.SaleDate )), 0)
It takes any date and returns the first Monday of the month in which that date occurred. In your case, however, you have to do a little more work because a sale might have occurred in the window between the first of the month and the first Monday of the month. The CASE statement detects that scenario and, if it's true, subtracts a week off of the date before calculating the first Monday.
Good luck!
-Michael
I have some code that takes in a year and month and returns the fiscal start and end dates. Perhaps this will give you something to go by:
DECLARE #yr int;
DECLARE #mo int;
SELECT #yr = 2011
SELECT #mo = 7
DECLARE #FiscalMonthStartDate datetime
DECLARE #FiscalMonthEndDate datetime
DECLARE #startOfMonth datetime
DECLARE #startOfNextMonth datetime
select #startOfMonth = CAST((CAST(#yr AS VARCHAR(4)) + '-' + CAST(#mo AS VARCHAR(2)) + '-' + '01') as DATE)
select #startOfNextMonth = CAST((CAST(#yr AS VARCHAR(4)) + '-' + CAST((#mo + 1) AS VARCHAR(2)) + '-' + '01') as DATE)
SELECT #FiscalMonthStartDate =
CASE
WHEN DATEPART(DW,#startOfMonth) = 0
THEN DATEADD(DD, 1, #startOfMonth)
ELSE
DATEADD(DD, 8 - DATEPART(DW,#startOfMonth), #startOfMonth)
END
SELECT #FiscalMonthEndDate =
CASE
WHEN DATEPART(DW,#startOfNextMonth) = 0
THEN DATEADD(DD, 1, #startOfNextMonth)
ELSE
DATEADD(DD, 8 - DATEPART(DW,#startOfNextMonth), #startOfNextMonth)
END
-- subtract one day to get end of fiscal month (not start of next fiscal month)
SELECT #FiscalMonthEndDate = DATEADD(DD, -1, #FiscalMonthEndDate)
SELECT #FiscalMonthStartDate, #FiscalMonthEndDate

Get the records of last month in SQL server

I want to get the records of last month based on my db table [member] field "date_created".
What's the sql to do this?
For clarification,
last month - 1/8/2009 to 31/8/2009
If today is 3/1/2010, I'll need to get the records of 1/12/2009 to 31/12/2009.
All the existing (working) answers have one of two problems:
They will ignore indices on the column being searched
The will (potentially) select data that is not intended, silently corrupting your results.
1. Ignored Indices:
For the most part, when a column being searched has a function called on it (including implicitly, like for CAST), the optimizer must ignore indices on the column and search through every record. Here's a quick example:
We're dealing with timestamps, and most RDBMSs tend to store this information as an increasing value of some sort, usually a long or BIGINTEGER count of milli-/nanoseconds. The current time thus looks/is stored like this:
1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
You don't see the 'Year' value ('2014') in there, do you? In fact, there's a fair bit of complicated math to translate back and forth. So if you call any of the extraction/date part functions on the searched column, the server has to perform all that math just to figure out if you can include it in the results. On small tables this isn't an issue, but as the percentage of rows selected decreases this becomes a larger and larger drain. Then in this case, you're doing it a second time for asking about MONTH... well, you get the picture.
2. Unintended data:
Depending on the particular version of SQL Server, and column datatypes, using BETWEEN (or similar inclusive upper-bound ranges: <=) can result in the wrong data being selected. Essentially, you potentially end up including data from midnight of the "next" day, or excluding some portion of the "current" day's records.
What you should be doing:
So we need a way that's safe for our data, and will use indices (if viable). The correct way is then of the form:
WHERE date_created >= #startOfPreviousMonth AND date_created < #startOfCurrentMonth
Given that there's only one month, #startOfPreviousMonth can be easily substituted for/derived by:
DATEADD(month, -1, #startOfCurrentMonth)
If you need to derive the start-of-current-month in the server, you can do it via the following:
DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
A quick word of explanation here. The initial DATEDIFF(...) will get the difference between the start of the current era (0001-01-01 - AD, CE, whatever), essentially returning a large integer. This is the count of months to the start of the current month. We then add this number to the start of the era, which is at the start of the given month.
So your full script could/should look similar to the following:
DECLARE #startOfCurrentMonth DATETIME
SET #startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)
SELECT *
FROM Member
WHERE date_created >= DATEADD(month, -1, #startOfCurrentMonth)
AND date_created < #startOfCurrentMonth
All date operations are thus only performed once, on one value; the optimizer is free to use indices, and no incorrect data will be included.
SELECT *
FROM Member
WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate()))
AND DATEPART(yyyy, date_created) = DATEPART(yyyy, DATEADD(m, -1, getdate()))
You need to check the month and year.
Add the options which have been provided so far won't use your indexes at all.
Something like this will do the trick, and make use of an index on the table (if one exists).
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StartDate = dateadd(mm, -1, getdate())
SET #StartDate = dateadd(dd, datepart(dd, getdate())*-1, #StartDate)
SET #EndDate = dateadd(mm, 1, #StartDate)
SELECT *
FROM Member
WHERE date_created BETWEEN #StartDate AND #EndDate
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StartDate = DATEADD(mm, DATEDIFF(mm,0,getdate())-1, 0)
SET #EndDate = DATEADD(mm, 1, #StartDate)
SELECT *
FROM Member
WHERE date_created BETWEEN #StartDate AND #EndDate
An upgrade to mrdenny's solution, this way you get exactly last month from YYYY-MM-01
Last month consider as till last day of the month.
31/01/2016 here last day of the month would be 31 Jan. which is not similar to last 30 days.
SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
One way to do it is using the DATEPART function:
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = 4
and DATEPART(year, date_created) = 2009
will return all dates in april. For last month (ie, previous to current month) you can use GETDATE and DATEADD as well:
select field1, field2, fieldN from TABLE where DATEPART(month, date_created)
= (DATEPART(month, GETDATE()) - 1) and
DATEPART(year, date_created) = DATEPART(year, DATEADD(m, -1, GETDATE()))
declare #PrevMonth as nvarchar(256)
SELECT #PrevMonth = DateName( month,DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)) +
'-' + substring(DateName( Year, getDate() ) ,3,4)
SQL query to get record of the present month only
SELECT * FROM CUSTOMER
WHERE MONTH(DATE) = MONTH(CURRENT_TIMESTAMP) AND YEAR(DATE) = YEAR(CURRENT_TIMESTAMP);
SELECT * FROM Member WHERE month(date_created) = month(NOW() - INTERVAL 1 MONTH);
select * from [member] where DatePart("m", date_created) = DatePart("m", DateAdd("m", -1, getdate())) AND DatePart("yyyy", date_created) = DatePart("yyyy", DateAdd("m", -1, getdate()))
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StartDate = DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)
SET #EndDate = dateadd(dd, -1, DATEADD(mm, 1, #StartDate))
SELECT * FROM Member WHERE date_created BETWEEN #StartDate AND #EndDate
and another upgrade to mrdenny's solution.
It gives the exact last day of the previous month as well.
WHERE
date_created >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0)
AND date_created < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
I'm from Oracle env and I would do it like this in Oracle:
select * from table
where trunc(somedatefield, 'MONTH') =
trunc(sysdate -INTERVAL '0-1' YEAR TO MONTH, 'MONTH')
Idea: I'm running a scheduled report of previous month (from day 1 to the last day of the month, not windowed). This could be index unfriendly, but Oracle has fast date handling anyways.
Is there a similar simple and short way in MS SQL? The answer comparing year and month separately seems silly to Oracle folks.
You can get the last month records with this query
SELECT * FROM dbo.member d
WHERE CONVERT(DATE, date_created,101)>=CONVERT(DATE,DATEADD(m, datediff(m, 0, current_timestamp)-1, 0))
and CONVERT(DATE, date_created,101) < CONVERT(DATE, DATEADD(m, datediff(m, 0, current_timestamp)-1, 0),101)
I don't think the accepted solution is very index friendly
I use the following lines instead
select * from dbtable where the_date >= convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120) and the_date <= dateadd(ms, -3, convert(varchar(10),DATEADD(m, 0, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120));
Or simply (this is the best).
select * from dbtable where the_date >= convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120) and the_date < SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120);
Some help
-- Get the first of last month
SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120);
-- Get the first of current month
SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120);
--Get the last of last month except the last 3milli seconds. (3miliseconds being used as SQL express otherwise round it up to the full second (SERIUSLY MS)
SELECT dateadd(ms, -3, convert(varchar(10),DATEADD(m, 0, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120));
Here is what I did so I could put it in a view:
ALTER view [dbo].[MyView] as
with justdate as (
select getdate() as rightnow
)
, inputs as (
select dateadd(day, 1, EOMONTH(jd.rightnow, -2)) as FirstOfLastMonth
,dateadd(day, 1, EOMONTH(jd.rightnow, -1)) as FirstOfThisMonth
from justdate jd
)
SELECT TOP 10000
[SomeColumn]
,[CreatedTime]
from inputs i
join [dbo].[SomeTable]
on createdtime >= i.FirstOfLastMonth
and createdtime < i.FirstOfThisMonth
order by createdtime
;
Note that I intentionally ran getdate() once.
In Sql server for last one month:
select * from tablename
where order_date > DateAdd(WEEK, -1, GETDATE()+1) and order_date<=GETDATE()
DECLARE #curDate INT = datepart( Month,GETDATE())
IF (#curDate = 1)
BEGIN
select * from Featured_Deal
where datepart( Month,Created_Date)=12 AND datepart(Year,Created_Date) = (datepart(Year,GETDATE())-1)
END
ELSE
BEGIN
select * from Featured_Deal
where datepart( Month,Created_Date)=(datepart( Month,GETDATE())-1) AND datepart(Year,Created_Date) = datepart(Year,GETDATE())
END
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StartDate = dateadd(mm, -1, getdate())
SET #StartDate = dateadd(dd, datepart(dd, getdate())*-1, #StartDate)
SET #EndDate = dateadd(mm, 1, #StartDate)
set #StartDate = DATEADD(dd, 1 , #StartDate)
The way I fixed similar issue was by adding Month to my SELECT portion
Month DATEADD(day,Created_Date,'1971/12/31') As Month
and than I added WHERE statement
Month DATEADD(day,Created_Date,'1971/12/31') = month(getdate())-1
If you are looking for last month so try this,
SELECT
FROM #emp
WHERE DATEDIFF(MONTH,CREATEDDATE,GETDATE()) = 1
If you are looking for last month so try this,
SELECT
FROM #emp
WHERE DATEDIFF(day,CREATEDDATE,GETDATE()) between 1 and 30
A simple query which works for me is:
select * from table where DATEADD(month, 1,DATEFIELD) >= getdate()
If you are looking for previous month data:
date(date_created)>=date_sub(date_format(curdate(),"%Y-%m-01"),interval 1 month) and
date(date_created)<=date_sub(date_format(curdate(),'%Y-%m-01'),interval 1 day)
This will also work when the year changes. It will also work on MySQL.