December 1, 2016 at 7:25 am
Hi - please can someone point me in the right direction for working out the following problem in SQL.
I have 2 date fields - start and end dates and another field with number of working days. The data relates to how many working days someone was absent and I need to group this into month.
For example 20 working days total, 11 in August, 9 in September. I don't have access to low level data which would make this a lot easier.
Is this even possible using these 3 columns?
Many thanks in advance,
DSC
December 1, 2016 at 7:30 am
Okay... rereading this... A Calendar table won't necessarily work. I think this will only work if you know what month all of the absents occurred in. If you can't determine that, then there's not really any way to get the right answer.
Say I have a person who is absent 12 workdays in October and November. How do I know what month the person was absent?
Do you have some sample data that you could post?
December 1, 2016 at 8:43 am
Thanks for the reply - I'll have a read through and see if I can implement it via temp tables. Looks promising! 🙂
December 1, 2016 at 8:50 am
Hi,
Sure, the FROMDATE field is the 1st day of the absence and the UNTILDATE field is the last day.
Example data:
FROMDATE UNTILDATEWORKDAYS
09/08/201606/09/201620
From what I've read on the below article I think it is possible, I just need to build the prerequisite tables, join on them and group on the work days column if my understanding is correct.
December 1, 2016 at 9:57 am
Some DDL and easily consumable data would help circumvent any confusion but here's some sample code to get you started. Thom referred you to a calendar table article - that's the way to go. I'm going to ignore holidays for now and assume that a "working day" is Mon-Fri. Here's some sample data and an example of how to count the "work days".
-- test data
DECLARE @yourTable TABLE (EMPID int identity, FROMDATE date, UNTILDATE date, WORKDAYS int);
INSERT @yourTable (FROMDATE, UNTILDATE)
VALUES ('20160809', '20160906'), ('20160301', '20160405');
-- How to get working days: For now we're talking about Mon-Fri
WITH
E AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(c)),
iTally AS (SELECT N = ROW_NUMBER() OVER (ORDER BY (SELECT 1))-1 FROM E a, E b, E c)
SELECT EMPID, FROMDATE, UNTILDATE, WORKDAYS = COUNT(*)
FROM @yourTable yt
CROSS APPLY
(
SELECT TOP (DATEDIFF(DAY, yt.FROMDATE, yt.UNTILDATE)+1)
DATEADD(DAY, N, FROMDATE),
DATEPART(WEEKDAY, (DATEADD(DAY, N, FROMDATE)))
FROM iTally
) dd(dt,d)
WHERE d NOT IN (1,7)
GROUP BY EMPID, FROMDATE, UNTILDATE;
Now let's say you needed to update a table to include working days....
DECLARE @yourTable TABLE (EMPID int identity, FROMDATE date, UNTILDATE date, WORKDAYS int);
INSERT @yourTable (FROMDATE, UNTILDATE)
VALUES ('20160809', '20160906'), ('20160301', '20160405');
-- Add the previous result set to a CTE and update like so
WITH
E AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(c)),
iTally AS (SELECT N = ROW_NUMBER() OVER (ORDER BY (SELECT 1))-1 FROM E a, E b, E c),
CalculateWorkDays AS
(
SELECT EMPID, FROMDATE, UNTILDATE, WORKDAYS = COUNT(*)
FROM @yourTable yt
CROSS APPLY
(
SELECT TOP (DATEDIFF(DAY, yt.FROMDATE, yt.UNTILDATE)+1)
DATEADD(DAY, N, FROMDATE),
DATEPART(WEEKDAY, (DATEADD(DAY, N, FROMDATE)))
FROM iTally
) dd(dt,d)
WHERE d NOT IN (1,7)
GROUP BY EMPID, FROMDATE, UNTILDATE
)
UPDATE @yourTable
SET WORKDAYS = cw.WORKDAYS
FROM CalculateWorkDays cw;
SELECT * FROM @yourTable;
-- Itzik Ben-Gan 2001
December 1, 2016 at 10:02 am
Thank you so much for the example code above - I think I'm close to cracking it using the article Thom provided.
I wasn't sure if the problem was solvable so just wanted to know if the theory was possible.
Thank you all for replying and pointing me in the right direction, it's much appreciated.
December 9, 2016 at 3:57 pm
Referring to the article on the calendar table, you could add a [month] column that would makes this easy for you.
You would create the field and update it by adapting the following:
select [calendardate]
, dateadd(d,-day([calendardate])+1,[calendardate])
from calendar
From here the calculation becomes a simple matter.
select[month], count(*) numWorkDays
fromCalendar
where[calendardate]>= @fromDate and [calendardate]<=@untilDate and
workday = 1
group
by [month]
----------------------------------------------------
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply