Excel: No. of Weekdays in a given week - vba

My Data
A B C
1 Created Date Week No. of WorkDays
2 6/20/2018 11:36 06-w4 5
3 6/26/2018 12:56 06-w5 5
4 7/6/2018 23:01 07-w1 5
5 6/18/2018 18:11 06-w4 5
6 6/15/2018 12:01 06-w3 5
7 6/1/2018 13:31 06-w1 1
8 6/8/2018 12:17 06-w2 5
9 6/1/2018 13:32 06-w1 1
10 7/30/2018 13:32 07-w5 2
I have a week function that says whether an issue was created in Week 1 or 2 or so on. But for my calculation I need to consider workdays in that week, how do I do it. I'm calculating the no. of weekdays in that week manually now.
For example: June Week 1: No. of Weekdays is 1, because June 1 is Friday and June 2 is Saturday. Similarly for July Week 5 it is 2 days because July 29 is Sunday, July 30 & 31 are the weekdays.
My current formula for Week is
=CONCATENATE(TEXT(A1,"MM"),"-w",WEEKNUM(A1,1)-WEEKNUM(DATE(YEAR(A1),MONTH(A1),1),1)+1)
I'm trying out to use Workday function, but it does not provide my desired result.
Kindly help me out with this.

If the date in the A column is always a weekday, you can use this:
If that date can also be a weekend day, it will take the working days of the previous week. If you want to take the workinf days of the next week, you have to fiddle around still a bit.
=MIN(5,IF(MONTH(A2-WEEKDAY(A2,3))<MONTH(A2),7-WEEKDAY(DATE(YEAR(A2),MONTH(A2),1),1),IF(MONTH(A2+5-WEEKDAY(A2,2))>MONTH(A2),WEEKDAY(DATE(YEAR(A2),MONTH(A2)+1,0),2),5)))
First MIN: restrict to max 5 working days
First IF(): check if monday before or on date in A2 is in previous month
If so: take 7 minus weekday of first of month (sunday being 1)
If not so: second IF: check if friday this week is in next month
If so: take the weekday of the last of this month (monday being 1)
If not so: week in the middle of month, return 5
This of course does not take into account public holidays, only weekends.

For an inclusive # or workdays (e.g. Friday is 1 workday) try,
=NETWORKDAYS.INTL(A2, A2+5-WEEKDAY(A2,2), 1)
NETWORKDAYS.INTL allows for an optional holiday list if you want to create one.

Wrote my own VBA Formula - Results are as below
A B C D
1 Created Date Week No. of WorkDays No. of Days - Formula
2 6/20/2018 11:36 06-w4 5 5
3 3/2/2018 12:56 03-w1 2 2
4 7/6/2018 23:01 07-w1 5 5
5 6/18/2018 18:11 06-w4 5 5
6 6/15/2018 12:01 06-w3 5 5
7 6/1/2018 13:31 06-w1 1 1
8 6/8/2018 12:17 06-w2 5 5
9 6/1/2018 13:32 06-w1 1 1
10 7/30/2018 13:32 07-w5 2 2
Formula
=CalculateWorkdaysInWeek(A2)
VBA Code
Function CalculateWorkdaysInWeek(WeekRange As Range) As Variant
'Assume Week 2, 3 & 4 will always have 5 days
Dim WeekNo As Double
'Check if Week is 1 or 5
WeekNo = (Application.WorksheetFunction.WeekNum(WeekRange, 1) - _
Application.WorksheetFunction.WeekNum(DateSerial(Year(WeekRange), Month(WeekRange), 1))) + 1
Dim NoOfWeekDays As Integer
If WeekNo = 1 Then
FirstWeekDay = 7 - Weekday(DateSerial(Year(WeekRange), Month(WeekRange), 1), vbSunday)
If FirstWeekDay > 5 Then
FirstWeekDay = 5
End If
NoOfWeekDays = FirstWeekDay
ElseIf WeekNo = 5 Then
'Check the last day of the month as Monday as Start
LastWeekDay = Weekday(DateSerial(Year(WeekRange), Month(WeekRange) + 1, 0), vbMonday)
If LastWeekDay > 5 Then
LastWeekDay = 5
End If
NoOfWeekDays = LastWeekDay
Else ' Week 2,3 & 4 Return 5
NoOfWeekDays = 5
End If
CalculateWorkdaysInWeek = NoOfWeekDays
End Function

Related

count number of records by month over the last five years where record date > select month

I need to show the number of valid inspectors we have by month over the last five years. Inspectors are considered valid when the expiration date on their certification has not yet passed, recorded as the month end date. The below SQL code is text of the query to count valid inspectors for January 2017:
SELECT Count(*) AS RecordCount
FROM dbo_Insp_Type
WHERE (dbo_Insp_Type.CERT_EXP_DTE)>=#2/1/2017#);
Rather than designing 60 queries, one for each month, and compiling the results in a final table (or, err, query) are there other methods I can use that call for less manual input?
From this sample:
Id
CERT_EXP_DTE
1
2022-01-15
2
2022-01-23
3
2022-02-01
4
2022-02-03
5
2022-05-01
6
2022-06-06
7
2022-06-07
8
2022-07-21
9
2022-02-20
10
2021-11-05
11
2021-12-01
12
2021-12-24
this single query:
SELECT
Format([CERT_EXP_DTE],"yyyy/mm") AS YearMonth,
Count(*) AS AllInspectors,
Sum(Abs([CERT_EXP_DTE] >= DateSerial(Year([CERT_EXP_DTE]), Month([CERT_EXP_DTE]), 2))) AS ValidInspectors
FROM
dbo_Insp_Type
GROUP BY
Format([CERT_EXP_DTE],"yyyy/mm");
will return:
YearMonth
AllInspectors
ValidInspectors
2021-11
1
1
2021-12
2
1
2022-01
2
2
2022-02
3
2
2022-05
1
0
2022-06
2
2
2022-07
1
1
ID
Cert_Iss_Dte
Cert_Exp_Dte
1
1/15/2020
1/15/2022
2
1/23/2020
1/23/2022
3
2/1/2020
2/1/2022
4
2/3/2020
2/3/2022
5
5/1/2020
5/1/2022
6
6/6/2020
6/6/2022
7
6/7/2020
6/7/2022
8
7/21/2020
7/21/2022
9
2/20/2020
2/20/2022
10
11/5/2021
11/5/2023
11
12/1/2021
12/1/2023
12
12/24/2021
12/24/2023
A UNION query could calculate a record for each of 50 months but since you want 60, UNION is out.
Or a query with 60 calculated fields using IIf() and Count() referencing a textbox on form for start date:
SELECT Count(IIf(CERT_EXP_DTE>=Forms!formname!tbxDate,1,Null)) AS Dt1,
Count(IIf(CERT_EXP_DTE>=DateAdd("m",1,Forms!formname!tbxDate),1,Null) AS Dt2,
...
FROM dbo_Insp_Type
Using the above data, following is output for Feb and Mar 2022. I did a test with Cert_Iss_Dte included in criteria and it did not make a difference for this sample data.
Dt1
Dt2
10
8
Or a report with 60 textboxes and each calls a DCount() expression with criteria same as used in query.
Or a VBA procedure that writes data to a 'temp' table.

How to Find Week number, Period and year from Date in Redshift? (Week Starting with Wednesday and ends up with Tuesday)

Need to find weekNumber like 1,2,3,4 but the week starts with Wednesday and ends with Tuesday from date column and after the 4th week, again the week restart by again as the 1st week and so on (no need to consider month).
Need to find the Period based on weekNumber only, 4 weeks as 1 Period and Periods end with 13 (period 1-13) will restart again 1st period.
(4 weeks = 1 period) (no need to consider month).
Now need to calculate the businessyear based on Period. 13 Periods as One businessyear. (13 periods = 1 year)
Calculation logic:
7 days * 4 weeks = 28 days = 1 period
13 periods = 1 businessyear
Example:
A year has 365 days normally
In my scenario, 4 weeks * 7 days = 28 days
28 days *13 periods = 364 days
The remaining days will come as the 5th week and period 14.
Datekey date Year semistor Quarter Month DayName DayNum Wnumber
20090101 01-01-2009 2009 1 1 January 1 Thursday 1 0
20090102 02-01-2009 2009 1 1 January 1 Friday 2 0
20090103 03-01-2009 2009 1 1 January 1 Saturday 3 0
20090104 04-01-2009 2009 1 1 January 1 Sunday 0
20090105 05-01-2009 2009 1 1 January 1 Monday 0
20090106 06-01-2009 2009 1 1 January 1 Tuesday 6 0
20090107 07-01-2009 2009 1 1 January 1 Wednesday 0 0
20090108 08-01-2009 2009 1 1 January 1 Thursday 1 1
20090109 09-01-2009 2009 1 1 January 1 Friday 2 1
20090110 10-01-2009 2009 1 1 January 1 Saturday 3 1
20090111 11-01-2009 2009 1 1 January 1 Sunday 4 1
20090112 12-01-2009 2009 1 1 January 1 Monday 5 1
20090113 13-01-2009 2009 1 1 January 1 Tuesday 6 1
20090114 14-01-2009 2009 1 1 January 1 Wednesday 0 1
No need to consider the month in my scenario, need to consider leap year also (2016, 2020).
The traditional way to do this type of thing is to create a calendar table in the database. Then, your queries can simply JOIN to the calendar table to extract the relevant value.
I find that the easiest way to create the calendar table is to use Excel. Simply write some formulas that provide the desired values and Copy Down for the next decade or so. Then, save the sheet as CSV and load it into the database.
This way, you can totally avoid complex calculations involving database functions and you can use whatever rules you wish.

PLsql or Oracle Sql

Looking for a help on populating the data from table1 to table2.
I have table1 of below columns and data sample as below.
When days is 5 it needs to populate data on other table2 with 8 hours based on days (sat and sun needs to be 0 )
Table 1:
id year month days
101 2017 September 5
102 2017 September 4
103 2017 September 3
104 2017 September 2
Table 2 which needs to be populated as below:
Id Month 1 2(Sat) 3(Sunday) 4 5
101 September 8 0 0 8 8 8 8
102 September 8 0 0 8 8 8 0
103 September 8 0 0 8 8 0 0
104 September 8 0 0 8 0 0 0
You get the desired result with:
select
id,
month,
case when days >= 1 then 8 end as friday,
0 as saturday,
0 as sunday,
case when days >= 2 then 8 end as monday,
case when days >= 3 then 8 end as tuesday,
case when days >= 4 then 8 end as wednesday,
case when days >= 5 then 8 end as thursday
from table1
where year = 2017;
In order to fill table2 with this data, you can use an insert select:
insert into table2 (id, month, saturday, sunday, monday, tuesday, wednesday, thursday)
select
id,
...
from table1
where year = 2017;

Take one month back in teradata sql

I have some tables (samples are brought here) like this
scores (the score is calculated once in each month for each branch_cust in the 28 for specific month)
Branch_cust model_date score
1 28/12/2013 4
1 28/01/2014 3
1 28/02/2014 2
1 28/03/2014 7
1 28/04/2014 3
1 28/05/2014 5
1 28/06/2014 6
2 28/12/2013 9
2 28/01/2014 10
2 28/02/2014 12
2 28/03/2014 11
2 28/04/2014 10
2 28/05/2014 7
2 28/06/2014 8
loans:
Branch_cust agreement_date
1 05-01-2014
1 29-01-2014
2 27-02-2014
2 28-02-2014
Loans:
desired output:
Branch_cust agreement_date loan_open_score
1 05-01-2014 4
1 29-01-2014 3
2 27-02-2014 10
2 28-02-2014 12
Logic to create the loan_open_score :
If the day in the month of the agreement_date is less then "28" then bring the score of the month previous to the month of the agreement date.
If the day is greater or equal to "28" then bring the score for the month equal to the month of the agreement date.
Example: In the sample data for branch_cust = 1 the agreement_date was 05-01-2014 - meaning - day = 5 so I need to go back to Dec 2013 and take the score from there.
Any help how to do this? thank's. I was thinking of "join" and then substract 1 in "case of.." but I don't know how to handle the case when the date is 'dd-01-YYYY' in sql-teradata.
updated : column data type of the dates are dates.
trunc(agreement_date,'mon') + 27 returns the 28th of the current month. Now you can apply some logic and join on this calculated date:
case when trunc(agreement_date,'mon') + 27 > agreement_date
then add_months(trunc(agreement_date,'mon') + 27,-1)
else trunc(agreement_date,'mon') + 27
end
Another option would be to get the latest model_date per agreement date and join it to the scores table. This way you don't have to manipulate dates.
select t.branch_cust,t.agreement_Date,s.score
from scores s
join (select distinct l.branch_cust,l.agreement_Date
,max(s.model_Date) over(partition by l.branch_cust,l.agreement_Date) as max_model_Date
from scores s
join loans l on s.branch_cust=l.branch_cust and l.agreement_Date >= s.model_Date
) t
on s.branch_cust=t.branch_cust and s.model_Date=t.max_model_Date
select *
from scores as s
join loans as l
on l.Branch_cust =
s.Branch_cust
and l.model_date =
add_months
(
trunc(S.agreement_date,'mm')+27
,case when extract(day from s.agreement_date) < 28 then -1 else 0 end
)

Add date of first day of week to date dimension

I want to add a column to my date dimension that contains the date of the first day of that week. here's a piece of what it looks like
CalendarDate DayOfWeekNumber DayKey DayOfWeekName WeekNumber
1996-01-01 2 19960101 MONDAY 1
1996-01-02 3 19960102 TUESDAY 1
1996-01-03 4 19960103 WEDNESDAY 1
1996-01-04 5 19960104 THURSDAY 1
1996-01-05 6 19960105 FRIDAY 1
1996-01-06 7 19960106 SATURDAY 1
1996-01-07 1 19960107 SUNDAY 1
1996-01-08 2 19960108 MONDAY 2
1996-01-09 3 19960109 TUESDAY 2
1996-01-10 4 19960110 WEDNESDAY 2
1996-01-11 5 19960111 THURSDAY 2
1996-01-12 6 19960112 FRIDAY 2
1996-01-13 7 19960113 SATURDAY 2
1996-01-14 1 19960114 SUNDAY 2
So basically i would want a column WeekStartDate that, for each WeekNumber would have the CalendarDate of the first dayOfWeekNumber (dayOfWeekNumber =1)
It would look like
CalendarDate DayOfWeekNumber DayKey DayOfWeekName WeekNumber WeekStart
1996-01-01 2 19960101 MONDAY 1 1996-01-01
1996-01-02 3 19960102 TUESDAY 1 1996-01-01
1996-01-03 4 19960103 WEDNESDAY 1 1996-01-01
1996-01-04 5 19960104 THURSDAY 1 "
1996-01-05 6 19960105 FRIDAY 1 "
1996-01-06 7 19960106 SATURDAY 1 "
1996-01-07 1 19960107 SUNDAY 1 "
1996-01-08 2 19960108 MONDAY 2 1996-01-08
1996-01-09 3 19960109 TUESDAY 2 "
1996-01-10 4 19960110 WEDNESDAY 2 "
1996-01-11 5 19960111 THURSDAY 2 "
1996-01-12 6 19960112 FRIDAY 2
1996-01-13 7 19960113 SATURDAY 2
1996-01-14 1 19960114 SUNDAY 2
so something like
update myTable set WeekStartDate = CalendarDate where dayofweeknumber=2 (monday) for each weeknumber (pseudocode, i know that's not what literally what i want it to do).
Thanks for suggestions. Pretty sure I need to window on weeknumber.
UPDATE C
SET WeekStartDate = week_start
FROM
(
select *, week_start = min(CalendarDate)
over (partition by year(CalendarDate), WeekNumber)
from Calendar
) AS C