Results 1 to 8 of 8
  1. #1
    Mattbro is offline Competent Performer
    Windows XP Access 2003
    Join Date
    Mar 2012
    Posts
    100

    Modify SQL for calculating Bradford Factor to incorperate a rolling year


    Hello all,
    I was looking at a solution for a Bradford Factor database (calculate staff sickness based on days sick *days sick*no of sickness events). I saw this on another forum (http://www.access-programmers.co.uk/...d.php?t=229470);
    tblStaff with staffID, surname, forname etc.
    TblAbsence with AbsenceID, StaffID, AbsenceType (e.g. sick, compassionate), AbsenceStartDate and AbsenceLength.
    The SQL suggested was
    Code:
    SELECT tblStaff.StaffID, Sum([AbsenceLength])*Sum([AbsenceLength])*Count([AbsenceStartDate]) AS BradFordFactor, tblStaff.Surname, tblStaff.Forename, tblAbsence.AbsenceStartDate
    FROM tblStaff INNER JOIN tblAbsence ON tblStaff.StaffID = tblAbsence.StaffID
    GROUP BY tblStaff.StaffID, tblStaff.Surname, tblStaff.Forename, tblAbsence.AbsenceType, tblAbsence.AbsenceStartDate
    HAVING (((tblAbsence.AbsenceType)="sick") :
    This is great, but the Bradford Factor is calculated over a rolling year. I am trying to modify it on the AbsenceStartDate having to be less than one year from today. I have been playing with Date()>DateAdd("d",-365,Date() but am so far unsuccessful. Does anyone have any ideas how to incorporate it into the SQL?
    Many thanks,
    Mattbro

  2. #2
    June7's Avatar
    June7 is offline VIP
    Windows 7 64bit Access 2010 32bit
    Join Date
    May 2011
    Location
    The Great Land
    Posts
    53,770
    Criteria that compares the current date to a value calculated from the current date doesn't make sense. The criteria should be against a date field in the table.

    You only want to consider records that are between now and now-365?

    WHERE AbsenceStartDate BETWEEN Date()-365 AND Date()

    Or assuming there can't be records dated beyond the current date:

    WHERE AbsenceStartDate > Date()-365
    How to attach file: http://www.accessforums.net/showthread.php?t=70301 To provide db: copy, remove confidential data, run compact & repair, zip w/Windows Compression.

  3. #3
    Mattbro is offline Competent Performer
    Windows XP Access 2003
    Join Date
    Mar 2012
    Posts
    100
    Ah-right you are, June7
    Code:
    SELECT tblStaff.StaffID, Sum(tblAbsence.AbsenceLength) AS SumOfAbsenceLength, Count(tblAbsence.AbsenceStartDate) AS CountOfAbsenceStartDate, Sum([AbsenceLength])*Sum([AbsenceLength])*Count([AbsenceStartDate]) AS BradFordFactor, tblStaff.Surname, tblStaff.Forename
    FROM tblStaff INNER JOIN tblAbsence ON tblStaff.StaffID = tblAbsence.StaffID
    WHERE AbsenceStartDate BETWEEN Date()-365 AND Date()
    GROUP BY tblStaff.StaffID, tblAbsence.AbsenceType, tblStaff.Surname, tblStaff.Forename
    HAVING (((tblAbsence.AbsenceType)="sick"));
    Works a treat! Many thanks,
    Mattbro

  4. #4
    Mattbro is offline Competent Performer
    Windows XP Access 2003
    Join Date
    Mar 2012
    Posts
    100
    Hello all,
    I don't know if this will garner any attention, reopening my own thread, but it has just been pointed out to me that my formula is slightly incorrect. The Bradford factor is based on events*events*days, which is incorporated into the SQL (changed slightly from earlier, as I was using events*days*days!)
    Code:
    Sum([AbsenceLength])*Count([AbsenceStartDate])*Count([AbsenceStartDate]) AS BradFordFactor
    

    and it works on a rolling year, which is also incorporated using
    Code:
    BETWEEN Date()-365 AND Date()
    
    however, the formula doesn't allow for an individual who has had long term sick leave where the first day of absence is over a year ago but the last day of absence is less than a year ago. I need a count of days between:
    Date()-365 and the AbsenceEndDate IF the AbsenceStartDate >365 days ago AND the AbsenceEndDate is < 365 days ago.
    If that criteria exists, I then need to include it somehow by altering
    Code:
    Count(tblAbsence.AbsenceStartDate) AS CountOfAbsenceStartDate.
    I could do it by changing it to
    Code:
    Count(tblAbsence.AbsenceEndDate) ASCountofAbsenceEndDate
    If anyone can see how to code this, I would be very very interested as it is far beyond my capabilities...perhaps a second query?? Please help!
    Many thanks
    Mattbro

  5. #5
    orange's Avatar
    orange is online now Moderator
    Windows XP Access 2003
    Join Date
    Sep 2009
    Location
    Ottawa, Ontario, Canada; West Palm Beach FL
    Posts
    16,870

  6. #6
    Dal Jeanis is offline VIP
    Windows 7 32bit Access 2010 32bit
    Join Date
    May 2013
    Location
    Dallas TX
    Posts
    1,742
    I'd start by creating a subquery that creates/calculates the relevant absences, and then do the calc on that.

    This will give you the EFFECTIVE start and end dates and EFFECTIVE duration of each event in the period:
    Code:
    SELECT
       TA.StaffID,
       TA.AbsenceType,
       IIF(TA.AbsenceStartDate >= Date() - 365,
           TA.AbsenceStartDate, 
           Date() - 365
          ) As AbsenceStartDate,
       TA.AbsenceStartDate + TA.AbsenceLength As AbsenceEndDate,
       IIF(TA.AbsenceStartDate >= Date() - 365,
           TA.AbsenceLength,
           Int(TA.AbsenceStartDate + TA.AbsenceLength - Date() + 365)
          ) AS AbsenceLength
    FROM   
       tblAbsence AS TA
    WHERE  TA.AbsenceType="sick"
      AND  TA.AbsenceStartDate + TA.AbsenceLength >= Date() - 365;
    The Count of those records is the count of the events. The sum of the absenceLength is the total duration within the last year.

    Then Join to the tblStaff table to get the name. You don't need to group by the names, just accept the first one or max or min, since they're all the same for each staffID.

    Not sure why you wanted the AbsenceStartdate, or which of the possible dates that you really wanted. I'm going to give you the earliest start and latest end dates.

    So, your Bradford calc should look somewhat like this:
    Code:
    SELECT 
       TS.StaffID, 
       First(TS.Surname) As Surname, 
       First(TS.Forename) As Forename,
       Count(TA2.AbsenceLength])*Count(TA2.AbsenceLength])*Sum(TA2.AbsenceLength) AS BradFordFactor, 
       Min(TA2.AbsenceStartDate) AS FirstAbsence,
       Max(TA2.AbsenceEndDate) AS LastAbsence
    FROM 
       tblStaff AS TS 
       INNER JOIN 
         (SELECT
             TA.StaffID,
             TA.AbsenceType,
             IIF(TA.AbsenceStartDate >= Date() - 365,
                 TA.AbsenceStartDate, 
                 Date() - 365
                ) As AbsenceStartDate,
             TA.AbsenceStartDate + TA.AbsenceLength As AbsenceEndDate,
             IIF(TA.AbsenceStartDate >= Date() - 365,
                 TA.AbsenceLength,
                 Int(TA.AbsenceStartDate + TA.AbsenceLength - Date() + 365)
                ) AS AbsenceLength
          FROM   tblAbsence AS TA
          WHERE  TA.AbsenceType="sick"
            AND  TA.AbsenceStartDate + TA.AbsenceLength >= Date() - 365
          ) AS TA2
       ON TS.StaffID = TA2.StaffID
    GROUP BY 
       TS.StaffID;

  7. #7
    Mattbro is offline Competent Performer
    Windows XP Access 2003
    Join Date
    Mar 2012
    Posts
    100
    This is just fantastic! Many thanks, Dal-I am going to spend some time looking at the SQL here, to see if I can pick up some ideas. Thanks once again.
    Mattbro.

  8. #8
    Dal Jeanis is offline VIP
    Windows 7 32bit Access 2010 32bit
    Join Date
    May 2013
    Location
    Dallas TX
    Posts
    1,742
    No prob. A lot of times, when I have a complex one like this, I think in levels. If I had a table that had *this* information, then I could build my query pretty easily. How can I flatten *these* tables to make a query that mimics the talbe I want?

    In this case, the most complicated issue was how to turn the real absence table into an "effective" absence table, then the rest fell into place easily enough. You might want to verify whether that 365 should be 364 or 363 instead. The article said it's normally a 52-week (which is 364-day) rolling average, and I'm not sure whether you should include both today and the first day of that period.

Please reply to this thread with any new information or opinions.

Similar Threads

  1. Rolling Months within a Report
    By RayMilhon in forum Reports
    Replies: 5
    Last Post: 06-14-2013, 03:28 PM
  2. Rolling 90 day lookup Querie
    By Buddus in forum Queries
    Replies: 1
    Last Post: 08-20-2012, 02:09 PM
  3. Calculating Year to Date data in Form
    By barnes434 in forum Forms
    Replies: 3
    Last Post: 05-16-2012, 02:56 PM
  4. Rolling Total in Form
    By foxtrot in forum Forms
    Replies: 2
    Last Post: 01-26-2011, 05:45 AM
  5. Replies: 23
    Last Post: 06-30-2010, 02:05 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Other Forums: Microsoft Office Forums