The answer depends entirely on what your table layouts and relationships are.
1) How is "non-expired" training defined?
2) Do you want percentage of all personnel, or percentage of personnel who ever had that training?
3) Does all your training expire after the same time (1 year) or does it vary by course?
Assuming that your tables were set up like this...
Code:
tblStaff
StaffID AutoKey
StaffStatus Text (A = Active)
tblTraining
TrainingID AutoKey
TrainingName Text
TrainingExp Number (number of days training expires after)
tblStaffTraining
StaffTrainID AutoKey
StaffID Number (FK to tblStaff)
TrainingID Number (FK to tblTraining)
TrainingDate Date
Here's the total number of Active staff:
Code:
SELECT Count(StaffID) AS TotActiveStaff
FROM tblStaff
WHERE StaffStatus = "A";
which in certain places can also be written like
Code:
DCount([StaffID],[tblStaff],[StaffStatus]='A')
This query returns one record each active staff who has unexpired training of each kind. This step is needed because if a staff member has two unexpired trainings of the same kind, you don't want to double-count him:
Code:
SELECT
tblTraining.TrainingID,
First(tblTraining.TrainingName) As TrainingName,
tblStaff.StaffID
FROM ((tblStaff
INNER JOIN
tblStaffTraining
ON tblStaff.StaffID = tblStaffTraining.StaffID)
INNER JOIN
tblTraining
ON tblTraining.TrainingID = tblStaffTraining.TrainingID)
WHERE StaffStatus = "A"
AND DateAdd("d", tblTraining.TrainingExp, tblStaffTraining.TrainingDate) < Date()
GROUP BY
tblTraining.TrainingID, tblStaff.StaffID;
Here's the count and percent of the number of staff members for each training above:
Code:
SELECT
Q1.TrainingID,
First(Q1.TrainingName) As TrainingName,
Count(Q1.StaffID) As NbrTrained,
DCount([StaffID],[tblStaff],[StaffStatus]="A") As TotalStaff,
Count(Q1.StaffID)/(DCount([StaffID],[tblStaff],[StaffStatus]="A")) As PctTrained
FROM
(
SELECT
tblTraining.TrainingID,
First(tblTraining.TrainingName) As TrainingName,
tblStaff.StaffID
FROM ((tblStaff
INNER JOIN
tblStaffTraining
ON tblStaff.StaffID = tblStaffTraining.StaffID)
INNER JOIN
tblTraining
ON tblTraining.TrainingID = tblStaffTraining.TrainingID)
WHERE StaffStatus = "A"
AND DateAdd("d", tblTraining.TrainingExp, tblStaffTraining.TrainingDate) < Date()
GROUP BY
tblTraining.TrainingID, tblStaff.StaffID
) AS Q1
GROUP BY Q1.TrainingID;
Now, of course all this is probably Greek to you, but if you'll answer the question at the top, we can walk you through getting your answer, in short steps pretty much like the above.