I know the year and the quarter (e.g. "2010" and "4") for a schedule-related milestone and I want to select/create a datetime from it. There are a number of nifty ways to identify the quarter with formats ("qq") of a particular date, but not to go the other way around (or are there?). This is with t-sql / SQL Server.
Note: the datetime should be for the last day of that quarter.
UPDATE: Here is the solution that I ended up using courtesy of gbn, with AaronLS's variable names and then shortened-and-sweetened with Frank Kalis' suggestion :-) It was important to test for all 4 quarters to make sure the year is handled properly. Thanks to everyone who answered!
DECLARE #TheQuarter INT
DECLARE #theYear INT
-- Note: qq = q = quarter for the datepart
SET #TheQuarter = 1
SET #TheYear = 2011
SELECT DATEADD(YEAR, #TheYear-1900, DATEADD(qq, #TheQuarter, -1))
-- 2011-03-31 00:00:00.000
SET #TheQuarter = 2
SET #TheYear = 2011
SELECT DATEADD(YEAR, #TheYear-1900, DATEADD(qq, #TheQuarter, -1))
-- 2011-06-30 00:00:00.000
SET #TheQuarter = 3
SET #TheYear = 2011
SELECT DATEADD(YEAR, #TheYear-1900, DATEADD(qq, #TheQuarter, -1))
-- 2011-09-30 00:00:00.000
SET #TheQuarter = 4
SET #TheYear = 2011
SELECT DATEADD(YEAR, #TheYear-1900, DATEADD(qq, #TheQuarter, -1))
-- 2011-12-31 00:00:00.000
Here are a few q's that fetch the quarter from the date but not the other way around:
Calculate the Last Day in the CURRENT quarter; Calculate the last day of the quarter; Best way to store quarter and year in SQL Server?
Never use strings for datetime conversions: too much to go wrong with formats, language etc.
Keep it in the datetime type...
Select dateadd(day, -1,
dateadd(year, #year-1900,
dateadd(quarter, #qq, 0)
)
)
Looks like you've already found your solution, but just for the sake of it...
If you choose a different base date, you can shorten the whole thing to
SELECT DATEADD(YEAR, #TheYear-1900, DATEADD(qq, #TheQuarter, -1))
Since 0 indicates SQL Server's base date of 01.01.1900 (and the first day of a month), using -1 as base date starts off 1 day earlier and then you already have your last day of a month (and end of a quarter). Then you just need to do the rest of the datetime magic and voilĂ .
Just choose the date from the quarter:
select
case #theQuarter
when 1 then '3/31/' + cast(#theYear as varchar(4))
when 2 then '6/30/' + cast(#theYear as varchar(4))
when 3 then '9/30/' + cast(#theYear as varchar(4))
when 4 then '12/31/' + cast(#theYear as varchar(4))
end as quarterDate
Edit: Adjusted to be last day of quarter instead of first day.
This basically gets the first day of the following quarter, and then subtracts one so that you have the last day of the quarter you wanted. (#theQuarter + 1) adds one to the quarter, then *3 -2 gets the first month of that quarter, and % 12 is required when for the fourth quarter because you add one to 4 to get 5, which gives you 13 but you really want 1, so the % takes care of that.
Finally after casting it all to a date time, we have the first day of the following quarter, thus subtract - 1 at the end to subtract one day and get the last day of the quarter we initially put in.
declare #theQuarter as int;
set #theQuarter = 4;
declare #theYear as int;
set #theYear = 2009;
select
cast(
cast(
( (#theQuarter + 1) * 3 - 2) % 12
as varchar(2))
+ '-01-'
+ cast( (#theYear + (((#theQuarter + 1) * 3 - 2)/ 12) ) as varchar(4))
as datetime) - 1 ;
Related
As I have to calculate Start date of specific quarter and Quarter No from any financial year start date based on #firstMonthOfFiscalyear parameter. Let's say if #firstMonthOfFiscalyear =4 mean my financial year start date is 1 April and my quarter no start as below.
Q1 - April to Jun
Q2 - July to Sep
Q3 - Oct to Dec
Q4 - Jan to March
This quarter no will change based on #firstMonthOfFiscalyear parameter value.
From this I am able to get Quarter number but not able to get Start date of that quarter. So anyone can help me on this.
DECLARE #StartDateTime DATETIME
DECLARE #EndDateTime DATETIME
DECLARE #firstMonthOfFiscalyear int = 4 --Finanical year start month
SET #StartDateTime = '2017-04-01'
SET #EndDateTime = '2019-03-31';
WITH DateRange(Dates) AS
(
SELECT #StartDateTime as Date
Union ALL
SELECT DATEADD(d,1,Dates)
FROM DateRange
WHERE Dates < #EndDateTime
)
SELECT Dates
,FLOOR(((12 + MONTH(Dates) - #firstMonthOfFiscalyear) % 12) / 3 ) + 1 as quarterNo
, DATEADD(month, (IIF((month(dates)-#firstMonthOfFiscalyear)<0,(month(dates)-#firstMonthOfFiscalyear)+12,(month(dates)-#firstMonthOfFiscalyear))/3)*3, CAST( DATEFROMPARTS(year(dates),#firstMonthOfFiscalyear ,1) as Datetime)) as QuarterStartDate
FROM DateRange
OPTION (MAXRECURSION 0)
To calculate the fiscal quarter, you can just subtract the month difference and calculate the "real" quarter:
DATEPART(quarter, DATEADD(month, 1-#firstMonthOfFiscalyear, Dates))
To calculate the start of the quarter, calculate the start of the "real" quarter for the date reduced by the month difference and finally add the month difference again. The start of the "real" quarter of a #date can be calculated as follows, making use of the fact that DATEDIFF returns an integer and so the division by 3 is an integer division (do not remove the brackets, the multiplication has to be done after the integer division):
DATEADD(month, 3*(DATEDIFF(month, 0, #date)/3), 0)
Replacing #date with Dates, reduced by #firstMonthOfFiscalyear-1 months and adding #firstMonthOfFiscalyear-1 months in the end, this will be
DATEADD(month, #firstMonthOfFiscalyear-1, DATEADD(month, 3*(DATEDIFF(month, 0, DATEADD(month, 1-#firstMonthOfFiscalyear, Dates))/3), 0))
This can be simplified a little to
DATEADD(month, #firstMonthOfFiscalyear-1 + 3*((DATEDIFF(month, 0, Dates)+1-#firstMonthOfFiscalyear)/3), 0)
So in the end, your query could look like this:
SELECT Dates
, DATEPART(quarter, DATEADD(month, 1-#firstMonthOfFiscalyear, Dates)) AS quarterNo
, DATEADD(month, #firstMonthOfFiscalyear-1 + 3*((DATEDIFF(month, 0, Dates)+1-#firstMonthOfFiscalyear)/3), 0) AS QuarterStartDate
FROM DateRange
Since the start of the year can be found using DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0), just add #firstMonthOfFiscalyear - 1 months:
DATEADD(mm,#firstMonthOfFiscalyear,DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
How to get the first and last date of the current year?
Or by building the string:
CAST(CAST(#firstMonthOfFiscalyear AS VARCHAR(2)) + '/1/' CAST(DATEPART(YY,GETDATE()) AS VARCHAR(4)) AS DATE)
You can try this query to get start date of next 4 quarters based on your input. use DATEFROMPARTS function to build start date of first quarter then use CTE to build start date of next quarters by adding 3 months to previous quarter.
DECLARE #firstMonthOfFiscalyear int = 4
;WITH MyQuarters(q, qDate) as
(
select 1,
DATEFROMPARTS(year(getdate()), #firstMonthOfFiscalyear, 1) -- First quarter date
UNION ALL
select q+1,
DATEADD(q, 1, qdate) -- next quarter start date
from MyQuarters
where q <4 -- limiting the number of next quarters
)
select * from MyQuarters
Output:
q qDate
1 2018-04-01
2 2018-07-01
3 2018-10-01
4 2019-01-01
I need to get week numbers for some set of dates. For example, for Jan 2016 it should be something like:
[Week Number]
53 <--- for dates from Jan 1 to Jan 2
1 <--- for dates from Jan 3 to Jan 9
2 <--- for dates from Jan 10 to Jan 16
... <--- etc.
As you see, week should start from Sunday. I've used following function to set start day:
SET DATEFIRST 7
And this one to get week number:
DATEPART(ISOWK, SOME_DATE)
But I've noticed that DATEFIRST doesn't affect results when ISOWK being used - week always starts from Monday.
So, what am I doing wrong? Thank you!
UPD:
I've made a function, seems it works good:
CREATE FUNCTION [dbo].[GetWeekNumber]
(
#date as DATETIME,
#offset as INT
)
RETURNS NVARCHAR(100)
BEGIN
DECLARE #weekNumber as int
DECLARE #year as int
SET #date = DATEADD(MINUTE, #offset, #date)
SET #year = DATEPART(year, DATEADD(DAY, 1 - DATEPART(WEEKDAY, #date), CAST(#date AS DATE)))
IF ##DATEFIRST = 7
BEGIN
SET #date = DATEADD(day, 1, #date)
END
SET #weekNumber = DATEPART(ISO_WEEK, #date)
RETURN concat(#year, ', Week ', right('0' + convert(nvarchar, #weekNumber), 2))
END
You need to pass the date and timezone offset (in minutes). And SET DATEFIRST #startDay before executing this function (1 - Monday, 7 - Sunday). Example:
DECLARE #date as DATETIME
SET #date = '2016-01-03 12:00'
SET DATEFIRST 1
SELECT dbo.GetWeekNumber(#date, 0) -- 2015, Week 53
SET DATEFIRST 7
SELECT dbo.GetWeekNumber(#date, 0) -- 2016, Week 01
This is by design. According to MSDN:
ISO 8601 includes the ISO week-date system, a numbering system for
weeks. Each week is associated with the year in which Thursday occurs.
For example, week 1 of 2004 (2004W01) ran from Monday 29 December 2003
to Sunday, 4 January 2004.
So ISOWK is always based on Thursday, and is not affected by DATEFIRST.
To get the results you want, just use WEEK instead of ISOWK.
UPDATE: Also from MSDN:
January 1 of any year defines the starting number for the week
datepart, for example: DATEPART (wk, 'Jan 1, xxxx') = 1, where xxxx is
any year.
The only way to get Week #1 to be Jan 3-9 is to use math. Subtract one from the DATEPART(wk...) value, and if the result is 0, make it 53 (or simply use DATEADD on your date to subtract a week). There is no simpler way, as by design, the first week of any year will be the week that contains Jan 1.
In SQL Server 2008 i want to set a default date value of every Friday to show up in the column when i insert a new record?
ALTER TABLE myTable ADD CONSTRAINT_NAME DEFAULT GETDATE() FOR myColumn
Whats the best way to show every Friday?
I want the default value to be based on the now date then knowing that the next available date is 05-07/2013
I have the following:
dateadd(d, -((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate())
But when passing todays date, it gave me: 2013-06-28 which is actually LAST Friday!, it should be the up and coming Friday!
SELECT DATEADD(day,-3, DATEADD(week, DATEDIFF(week, 0, current_timestamp)+1, 0)) AS LastFridayDateOfWeek
Gets the last date of current week (sunday) then subtracts 3 from that to get Friday.
Replace current_timestamp if you need a different dates friday.
EDIT:
I thought about this a bit, and if the above (Friday THIS WEEK, so for Saturday it gives the previous date) does not work, you could easily use a reference date set like so:
DATEADD(DAY,7 + DATEDIFF(day,'20100109',#checkDateTime)/7*7,'20100108') as FridayRefDate
Same thing but with no hard coded Friday/Saturday in it:
DATEADD(DAY,7 + DATEDIFF(day,DATEADD(wk, DATEDIFF(wk,0,#checkDateTime),5),#checkDateTime)/7*7,DATEADD(wk, DATEDIFF(wk,0,#checkDateTime), 4))
So for 20100109 is a Friday.
SET #checkDateTime = '2012-01-14 3:34:00.000'
SELECT DATEADD(DAY,7 + DATEDIFF(day,'20100109',#checkDateTime)/7*7,'20100108') as FridayRefDate
it returns "2012/1/20"
But for SET #checkDateTime = '2012-01-13 3:34:00.000' it returns "2012/1/13"
If your current query gives you last Friday, the easiest thing to do is simply to add 7 to it:
select dateadd(d, 7-((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate())
------------------^
SELECT CONVERT(DATE, ( CASE WHEN DATEPART(dw, GETDATE()) - 6 <= 0
THEN DATEADD(dd,
( DATEPART(dw, GETDATE()) - 6 ) * -1,
GETDATE())
ELSE DATEADD(dd, ( DATEPART(dw, GETDATE()) ) - 1,
GETDATE())
END )) AS NearestFriday
Just add 7 to the formula
SELECT DATEADD(dd,CAST(5-GETDATE() AS int)%7,GETDATE()+7)
To verify the formula:
WITH test AS (
SELECT GETDATE() AS d UNION ALL
SELECT DATEADD(dd,1,d)
FROM test WHERE d < GETDATE() + 30
)
SELECT
d AS [input],
DATEADD(dd,CAST(5-d AS int)%7,d+7) AS [output]
FROM test
To tweak the the formula, adjust the 5- and the +7
I'm trying to write a sql query to get last week's count in the format of mm/count/yyyy. In my situation, Wednesday starts a new week. So today March 8th, 2012 is the second week of March, and the last week count is 03/01/2012. Please note, the 01 means week count not date. If consider March 1st, 2012, the last week count should be the last week of Feburary which is 02/05/2012
Update: Thanks for Steve's comment, reminding me to clear my question here. Each month starts from it's first Wednesday. So the 03/01/2012 starts from March 7th, 2012 to March 13th, 2012
Any sql query solution?
I'm using sql-server
Here's some date logic to get you started. I can't comprehend your funky "last week count" definition by the two examples, so I can't code it.
DECLARE
#Now datetime,
#Today datetime,
#MonthStart datetime,
#WeekCount int,
#Result varchar(10)
SET #Now = GetDate()
SET #Today = DateAdd(dd, DateDiff(dd, 0, #Now), 0)
SET #MonthStart = DateAdd(mm, DateDiff(mm, 0, #Today), 0)
-- relative to the actual day the month started
SET #WeekCount = ((DatePart(dd, #Today)-1) / 7) + 1
-- relative to Sunday
--SET #WeekCount = (DatePart(week, #Today) - (DatePart(week, #MonthStart) + 1
SET #Result = convert(varchar(10), #Today, 101)
SET #Result =
LEFT(#Result, 3) -- month/
+ RIGHT('z00' + convert(varchar(2), #WeekCount), 2) -- week with zero pad
+ RIGHT(#Result, 5) -- /year
SELECT
#Now as TheNow,
#Today as Today,
#MonthStart as MonthStart,
#WeekCount as WeekCount,
#Result as Result
See also SET DATEFIRST
in oracle:
select to_char( sysdate, 'w' ) from dual
#Steven,
Sorry, this didn't fit as a comment.
Your description of "[nth] week in [month]" is not clear. Your week starts on Wednesday. February first was a Wednesday, so the weeks in February, 2012, if there are indeed 5 of them, are
February 1-7
February 8-14
February 15-21
February 22-28 and
February 29 - March 6
You describe March 8 as being in the "second week of March," so the first week of March must be the previous week, which is February 29 - March 6. Note that this is also what you call "the last (fifth) week in February."
By your description, then, the weeks you write as '02/05/2012' and '03/01/2012' are the same week with different names.
What is the rule that lets you know that
You want the same "last week" when you run the program March 1 as when you run it March 8
You want that week (which is the same) described differently in these two cases.
Or does your question have a mistake in it.
Once you can describe what you need, it will be easy to program. If you don't know what you want, it will be impossible to program.
In SQL Server these queries return 1,1,2,5
select ((DATEPART(dd, 'March 01, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 07, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 08, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 31, 2012')-1)/7) + 1
So this may be what you need
declare #dt datetime = 'March 31, 2012'
select
CONVERT(nvarchar(4), DATEPART(month,#dt)) + '/' +
CONVERT(nvarchar(4), ((DATEPART(dd, #dt)-1)/7) + 1) + '/' +
CONVERT(nvarchar(4), DATEPART(year,#dt))
which produces '3/5/2012'
SELECT
RIGHT(100 + MONTH(D) , 2) + '/' +
RIGHT(100 + (DAY(D) + 6) / 7, 2) + '/' +
DATENAME(YEAR, D)
FROM (
SELECT DATEADD(WEEK, -1, GETDATE()) AS D
) s
I think that should do it, I don't get the value for last week because it was confusing and the answer is cleaner that way, you can just add a DATEADD(day,-7,date) somewhere.
SET DATEFORMAT YDM
CREATE TABLE #Dates (Date DATETIME)
INSERT INTO #Dates VALUES ('2012-31-03');
INSERT INTO #Dates VALUES ('2012-15-02');
INSERT INTO #Dates VALUES ('2012-02-04');
INSERT INTO #Dates VALUES ('2012-02-05');
WITH Mondays as (
SELECT DATEADD(week, DATEDIFF(week,0, DATEADD(day,6-DATEPART(day,d.Date),d.Date) ), 0) FirstMonday,
DATEADD(week, DATEDIFF(week,0, DATEADD(day,6-DATEPART(day,DATEADD(month, -1, d.Date)),DATEADD(month, -1, d.Date)) ), 0) FirstMondayOfLastMonth,
d.Date
FROM #Dates d),
Wednesday as (
SELECT CASE WHEN DATEPART(day,m.FirstMonday) <= 5
THEN DATEADD(day,2,m.FirstMonday)
ELSE DATEADD(day,-5,m.FirstMonday) END FirstWednesday,
CASE WHEN DATEPART(day,m.FirstMondayOfLastMonth) <= 5
THEN DATEADD(day,2,m.FirstMondayOfLastMonth)
ELSE DATEADD(day,-5,m.FirstMondayOfLastMonth) END FirstWednesdayOfLastMonth,
m.Date
FROM Mondays m)
SELECT w.Date,
CASE WHEN w.Date >= w.FirstWednesday THEN
RIGHT('0' + CAST(DATEPART(month,w.Date) AS NVARCHAR(2)),2)
+ '/0' + CAST(DATEDIFF(week,w.FirstWednesday, w.Date) + 1 AS NVARCHAR(2))
+ '/' + CAST(DATEPART(year,w.Date) AS NVARCHAR(4))
ELSE
RIGHT('0' + CAST(DATEPART(month,w.FirstWednesdayOfLastMonth) AS NVARCHAR(2)),2)
+ '/0' + CAST(DATEDIFF(week,w.FirstWednesdayOfLastMonth, w.Date) + 1 AS NVARCHAR(2))
+ '/' + CAST(DATEPART(year,w.FirstWednesdayOfLastMonth) AS NVARCHAR(4))
END AS weekDate
FROM Wednesday w
DROP TABLE #Dates
The result is :
Date weekDate
2012-03-31 00:00:00.000 03/04/2012
2012-02-15 00:00:00.000 02/03/2012
2012-04-02 00:00:00.000 03/05/2012
2012-05-02 00:00:00.000 05/01/2012
I have to calculate all the invoices which have been paid in the first 'N' days of a month. I have two tables
. INVOICE: it has the invoice information. The only field which does matter is called 'datePayment'
. HOLYDAYS: It is a one column table. Entries at this table are of the form "2009-01-01",
2009-05-01" and so on.
I should consider also Saturdays and Sundays
(this might be not a problem because I could insert those days at the Hollidays table in order to consider them as hollidays if neccesary)
The problem is to calculate which is the 'payment limit'.
select count(*) from invoice
where datePayment < PAYMENTLIMIT
My question is how to calculate this PAYMENTLIMIT. Where PAYMENTLIMIT is 'the fifth working day of every month'.
The query should be run under Mysql and Oracle therefore standard SQL should be used.
Any hint?
EDIT
In order to be consistent with the title of the question the pseudo-query should the read as follows:
select count(*) from invoice
where datePayment < FIRST_WORKING_DAY + N
then the question can be reduced to calculate the FIRST_WORKING_DAY of every month.
You could look for the first date in a month, where the date is not in the holiday table and the date is not a weekend:
select min(datePayment), datepart(mm, datePayment)
from invoices
where datepart(dw, datePayment) not in (1,7) --day of week
and not exists (select holiday from holidays where holiday = datePayment)
group by datepart(mm, datePayment) --monthnr
Something like this might work:
create function dbo.GetFirstWorkdayOfMonth(#Year INT, #Month INT)
returns DATETIME
as begin
declare #firstOfMonth VARCHAR(20)
SET #firstOfMonth = CAST(#Year AS VARCHAR(4)) + '-' + CAST(#Month AS VARCHAR) + '-01'
declare #currDate DATETIME
set #currDate = CAST(#firstOfMonth as DATETIME)
declare #weekday INT
set #weekday = DATEPART(weekday, #currdate)
-- 7 = saturday, 1 = sunday
while #weekday = 1 OR #weekday = 7
begin
set #currDate = DATEADD(DAY, 1, #currDate)
set #weekday = DATEPART(weekday, #currdate)
end
return #currdate
end
I'm not 100% sure about whether the "weekday" numbers are fixed or might depend on your locale on your SQL Server. Check it out!
Marc
Rather than a Holidays table of days to exclude, we use the calendar table approach: one row for every day the application will ever need (thirty years spans a modest 11K rows). So not only does it have an is_weekday column, it has other things relevant to the enterprise e.g. julianized_date. This way, every possible date would have a ready-prepared value for first_working_day_this_month and finding it involves a simple lookup (which SQL products tend to be optimized for!) rather than 'calculating' it each time on the fly.
We have dates table in our application (filled with all dates and date parts for some tens of years), what allows various "missing" date manipulations, like (in pseudo-sql):
select min(ourdates.datevalue)
from ourdates
where ourdates.year=<given year> and ourdates.month=<given month>
and ourdates.isworkday
and not exists (
select * from holidays
where holidays.datevalue=ourdates.datevalue
)
Ok, at a first stab, you could put the following code into a UDF and pass in the Year and Month as variables. It can then return TestDate which is the first working day of the month.
DECLARE #Month INT
DECLARE #Year INT
SELECT #Month = 5
SELECT #Year = 2009
DECLARE #FirstDate DATETIME
SELECT #FirstDate = CONVERT(varchar(4), #Year) + '-' + CONVERT(varchar(2), #Month) + '-' + '01 00:00:00.000'
DROP TABLE #HOLIDAYS
CREATE TABLE #HOLIDAYS (HOLIDAY DateTime)
INSERT INTO #HOLIDAYS VALUES('2009-01-01 00:00:00.000')
INSERT INTO #HOLIDAYS VALUES('2009-05-01 00:00:00.000')
DECLARE #DateFound BIT
SELECT #DateFound = 0
WHILE(#DateFound = 0)
BEGIN
IF(
DATEPART(dw, #FirstDate) = 1
OR
DATEPART(dw, #FirstDate) = 1
OR
EXISTS(SELECT * FROM #HOLIDAYS WHERE HOLIDAY = #FirstDate)
)
BEGIN
SET #FirstDate = DATEADD(dd, 1, #FirstDate)
END
ELSE
BEGIN
SET #DateFound = 1
END
END
SELECT #FirstDate
The things I don`t like with this solution though are, if your holidays table contains all days of the month there will be an infinite loop. (You could check the loop is still looking at the right month) It relies upon the dates being equal, eg all at time 00:00:00. Finally, the way I calculate the 1st of the month past in using string concatenation was a short cut. There are much better ways of finding the actual first day of the month.
Gets the first N working days of each month of year 2009:
select * from invoices as x
where
datePayment between '2009-01-01' and '2009-12-31'
and exists
(
select
1
from invoices
where
-- exclude holidays and sunday saturday...
(
datepart(dw, datePayment) not in (1,7) -- day of week
/*
-- Postgresql and Oracle have programmer-friendly IN clause
and
(datepart(yyyy,datePayment), datepart(mm,datePayment))
not in (select hyear, hday from holidays)
*/
-- this is the MSSQL equivalent of programmer-friendly IN
and
not exists
(
select * from holidays
where
hyear = datepart(yyyy,datePayment)
and hmonth = datepart(mm, datePayment)
)
)
-- ...exclude holidays and sunday saturday
-- get the month of x datePayment
and
(datepart(yyyy, datePayment) = datepart(yyyy, x.datePayment)
and datepart(mm, datePayment) = datepart(mm, x.datePayment))
group by
datepart(yyyy, datePayment), datepart(mm, datePayment)
having
x.datePayment < MIN(datePayment) + #N -- up to N working days
)
Returns the first Monday of the current month
SELECT DATEADD(
WEEK,
DATEDIFF( --x weeks between 1900-01-01 (Monday) and inner result
WEEK,
0, --1900-01-01
DATEADD( --inner result
DAY,
6 - DATEPART(DAY, GETDATE()),
GETDATE()
)
),
0 --1900-01-01 (Monday)
)
SELECT DATEADD(day, DATEDIFF (day, 0, DATEADD (month, DATEDIFF (month, 0, GETDATE()), 0) -1)/7*7 + 7, 0);
select if(weekday('yyyy-mm-01') < 5,'yyyy-mm-01',if(weekday('yyyy-mm-02') < 5,'yyyy-mm-02','yyyy-mm-03'))
Saturdays and Sundays are 5, 6 so you only need two checks to get the first working day