MS ACCESS - Finding field for most recent record - ms-access

Apologies for title, I am not sure how to phrase it.
I currently have two tables "ASSETS" and "LOANS"
ASSETS contains a straightforward list of equipment
It has a field "AssetID" which has a One-To-Many relationship with a field in LOANS called "LoanAssetID"
Each piece of equipment can have many loans. It can be loaned to one person, then returned, then loaned to another. There is a field in "LOANS" named "ReturnDate" in which people record the date that a piece of equipment was returned. There is also a field called "StartDate".
A piece of equipment can said to be currently 'on loan' if the most recent record (that with the most recent start date) has no return date.
However, I am not clear enough in my query writing to complete this. I need to find the most recent record as for any asset, there may be multiple return dates, but these may not always correspond to the most recent loan.
Ideally, I would then like this to calculate a field to mark the equipment as 'on loan' 'available' etc.
Thanks for any help in advance
So far I have tried a Max Query, but, probably due to me misunderstanding queries, I am confused as to why it returns more than one result.
So, currently I have tried
SELECT Max(tbl_Loans.[Start Date]) AS [MaxOfStart Date],tbl_Loans [Return Date], tbl_Loans.LoanAssetID
FROM tbl_Loans
GROUP BY tbl_Loans.[Return Date], tbl_Loans.LoanAssetID
HAVING (((tbl_Loans.[Return Date]) Is Null));
However, what I would like is the most recent value only for any given LoanAssetID; what I get is more than one field for each given LoanAssetID where more than one result exists.
Thank you for your help

The query is grouping by return date, which I don't believe you want. Try:
SELECT Max(tbl_Loans.[Start Date]) AS [MaxOfStart Date],tbl_Loans.[Return Date], tbl_Loans.LoanAssetID
FROM tbl_Loans
GROUP BY tbl_Loans.LoanAssetID
HAVING tbl_Loans.[Return Date] Is Null;
Alternatively, if your system is robust enough to assume that any null return date will correspond with the most recent loan since an asset that has yet to be returned could not be lent to a different individual, you could just search the table for Null return dates:
SELECT tbl_Loans.LoanAssetID
FROM tbl_Loans
GROUP BY tbl_Loans.LoanAssetID
HAVING tbl_Loans.[Return Date] Is Null

Related

How to Properly Create a SQL Query

Good Afternoon,
I am working on a database for someone that tracks the vehicles they use in their business. Due to vehicles having new license plates issued to them as they expire the business wants to track the current plate for each vehicle as well as all plates that were previously issued to each vehicle.
I have created a table for vehicles, tbl_vehicles.
I have also created a table for license plates, tbl_license_plates.
Being that each vehicle has multiple license plate records. I need on a form, frm_vehicles, (where certain data for each vehicle is updated) to show only the most recent license plate number to appear. This needs to happen even if the plate has expired...i.e...is no longer valid.
The problem that I am encountering is that I do not have sufficient SQL skills to construct a query that returns for each vehicle only the most recent plate. I wrote the below query and it returns the vehicle_master_id and the expiration date of the most recently issued plate.
However, when I try to add the license_plate_number to the query, it returns every plate that has every been issued for each vehicle. This is a problem because I need the query to return only the most recently issued plate, whether or not it is valid (unexpired).
So, the guidance that I am seeking is how to construct this query so that it returns the license_plate_number for only the most recently issued plate, regardless of validity.
Can someone point me in the right direction, please?
As suggested, here is the text of the query
SELECT tbl_license_plates.vehicle_master_id AS Vehicle, Max(tbl_license_plates.date_expires) AS Expiration_Date, tbl_license_plates.license_plate_number
FROM tbl_license_plates
GROUP BY tbl_license_plates.vehicle_master_id, tbl_license_plates.license_plate_number;
Consider:
SELECT tbl_License_Plates.* FROM tbl_License_Plates WHERE license_plate_master_ID IN
(SELECT TOP 1 license_plate_master_ID FROM tbl_License_Plates AS Dupe WHERE
Dupe.vehicle_master_ID = tbl_License_Plates.vehicle_master_ID ORDER BY date_issued DESC);
More info on subqueries http://allenbrowne.com/subquery-01.html
Another approach is to take your GROUP BY query that has vehicle ID and issue date and INNER JOIN with tbl_License_Plates with compound link on both ID and date fields. This will be a non-updatable query.
Consider using Max function to return max valid date, can find a lot on Google about that function. Something like:
SELECT tbl_License_Plates.vehicle_master_id, Max(tbl_License_Plates.date_expires) AS
MaxOfdate_expires
FROM tbl_License_Plates
GROUP BY tbl_License_Plates.vehicle_master_id;

PowerSchool: How to query past enrollment

I know this is somewhat of a specialized question since only a small percentage of members will even have heard of PowerSchool, but it's hard to find help for this. Given a start date and end date, I need to run a query that will return the student ID's for all students who were enrolled in the District during that time period. If I could use that with 'WITH AS', I could add it to an attendance query 'Where' clause like below. This is what I've got so far, but I don't know how to check it's accuracy:
SELECT * FROM Students
WHERE ID IN (
SELECT studentid FROM ps_adaadm_defaults_all
WHERE schoolid IN ('16', '28', '40')
AND calendardate >= '1-May-15'
AND calendardate <= '31-May-15'
GROUP BY studentid)
ORDER BY LastFirst;
"ps_adaadm_defaults_all" is a PowerSchool View that is mainly for ADM so my assumption here is that if a student ID exists in ps_adaadm_defaults_all with a date between the two given dates, that student was enrolled at least that day regardless of attendance, correct? Any PowerSchool users out there that can lend a hand?
I get results with this query but when I try to verify the accuracy by using the PowerSchool site, the results aren't exactly the same. What I mean by using the site is I log in as district admin, set Term to 15-16 year, School to desired school and select students whose last names begin with 'A'. I then start comparing the list it provides with the students from the query results whose last names begin with 'A'. I am noticing though that there are names that I get with my query that are not showing on the site and I think it's due to their exitdate being prior to the current schoolyear. Those students were obviously enrolled at that time, but their names aren't in the PowerSchool results. I'm thinking because they're not enrolled anymore? Is there any way for me to test the accuracy of this query? Am I even on the right track? Thanks in advance.
It sounds to me like you have two questions:
What is the best query to return all students who were enrolled during a given time period?
What is the best way to check that my query is selecting all records it should be?
I'd use the ps_enrollment view for your query. It includes student id, school id, and start and end dates, so it can be used to find all students who were enrolled at a certain point in time.
Students enrolled for the whole specified time period
SELECT UNIQUE pe.StudentID
FROM ps_enrollment pe
WHERE pe.schoolid IN ('16', '28', '40')
AND pe.EntryDate <= '05/01/2015'
AND pe.ExitDate >= '05/30/2015'
Students enrolled at any time within the specified time period
SELECT UNIQUE pe.StudentID
FROM ps_enrollment pe
WHERE pe.schoolid IN ('16', '28', '40')
AND (
(pe.EntryDate <= '05/01/2015' AND pe.ExitDate >= '05/01/2015')
OR (pe.EntryDate <= '05/30/2015' AND pe.ExitDate >= '05/30/2015')
OR (pe.EntryDate >= '05/01/2015' AND pe.ExitDate <= '05/30/2015')
)
In the above example, the three conditions inside the AND check for enrollments that either started before or on and ended after or on the first date, then the second date, and finally checks for any enrollments that happened in between the two dates.
Note: I used UNIQUE instead of GROUP BY. I think it fits what you're doing a little bit more.
The easiest way to check these numbers in the admin side is to use System Reports -> Membership and Enrollment -> Enrollment Summary by Date. This is an easy way to check enrolled students numbers at any point in time, and also will give you the list of those specific students. It includes inactive students.
You can double-check that it's working perfectly by entering a single date in your query instead of using a date range, and by checking that date against the Enrollment Summary by Date. When I did this for our district, my query pulled 7 extra records (out of over 7000), but upon investigation, all of those were due to bad reenrollment records, so it appears to be working correctly.
When you search PowerSchool from the admin website, it only returns active students regardless of what term you select. In other words, I can't select "2000-2001" from the terms list and magically have everything reflect that term.
I can think of a couple things that may be affecting your searches:
search by using a forward slash to include inactive students "/lastname"
if you are searching HS students - remember that seniors transfer to a special school when they graduate
A better way to verify your query results would be to use the ADA/ADM section under System Reports. Reduce your query to one date and then run the ADA/ADM by Date report for the same day.
Just came across this and for anyone that is reading through this, PowerSchool has come up with "as of" selections.
Examples:
*as_of=09/30/2020;enroll_status=0
*as_of=09/30/2020;track=D

Find duplicate between two dates with same Employee ID and same child name in vba access

I have a Form name frmCEA1 and a Table named tabsubCEA. Field names are:
E_ID (which is Employee ID, number field)
FY (which is Financial Year, String i.e. 2014-15)
FChildPrFr ( Which is Claim start Date, Date ( dd-mmm-yy format))
FChildPrupto ( Which is Claim end Date, Date(dd-mmm-yy format))
There are also
four fields in table (tabSubCEA)
EID (which is Employee ID, number field),
FY (which is Financial Year, String i.e. 2014-15),
PeriodFrom ( Which is Claim start Date, Date ( dd-mmm-yy format)),
Periodtill ( Which is Claim end Date, Date(dd-mmm-yy format)).
An employee can process claim single times in a financial Year for single child and he/she can claim for maximum two child. He/She can claim separate for both child or can claim as combined. He/She can also claim for previous financial Year.
I processed claim for an employee for single child in Fin.Year 2014-15 now employee is going to claim his/her second child for same financial year and I processed it successfully.
I want to know that How can my form(frmCEA1) prevent me using (messagebox) if i goes to process claim for same information i.e. same E_ID, First or Second Child with same claim between starting and ending Period.
I tried so much but could not success. Kindly help...
This doesn't necessarily have to be done in VBA, but that is an option. Either way, a query needs to be run to extract the number of records that match a given situation.
When an employee is being processed, run a query against that employee ID within your tabSubCEA table to find the number of records that exist for the desired financial year. However, instead of returning the actual record data, just return the COUNT of the records. If I'm understanding your situation correctly, whenever the COUNT exceeds two, then you don't want to process the employee. The easiest way would be to disable whatever "submit" button on the form.
Your query, whether a created query that references fields on the form, or via VBA would look something like this:
SELECT
COUNT(*)
FROM
tabSubCEA
WHERE
EID = '<employee id here>' AND
FY = '<fiscal year here>' AND
PeriodFrom > '<application date here>' AND
Periodtill > '<application date here>'
This will count the number of records that the employee in question has successfully filed during the desired fiscal year with an active claim period.
Basically, what you're trying to extract from the system is a count of the number of records that meet a specific criteria to this situation. You're going to want something similar to this to validate the number of claims an employee is making.

Pulling different records from multiple tables as one transaction history list

I am working on an employee management/reward system and need to be able to show a single "transaction history" page that shows in chronological order the different events that the employee has experienced in one list. (Sort of like how in facebook you can goto your history/action section and see a chronological list of all the stuff that you have done and affects you, even though they are unrelated to eachother and just have you as a common user)
I have different tables for the different events, each table has an employee_id key and an "occured" timestamp, some table examples:
bonuses
customers
raise
complaints
feedback
So whenever an event occurs (ie a new customer is assigned to the employee, or the employee gets a complaint or raise) a new row is added to the appropriate table with the employee ID it affects and a timestamp of when it occured.
I need a single query to pull all records (upto 50 for example) that include the employee and return a history view of that employee. The field names are different in each table (ie the bonus includes an amount with a note, the customer includes customer info etc).
I need the output to be a summary view using column names such as:
event_type = (new customer, bonus, feedback etc)
date
title (a brief worded title of the type of event, specified in sql based on the table its referencing)
description (verbiage about the action, such as if its event_type bonus display the bonus amount here, if its a complain show the first 50 characters of the complaint message or the ID of the user that filed the complaint from the complaints table. All done in SQL using if statements and building the value of this field output based on which table it comes from. Such as if its from the customers table IF current_table=customers description='A customer was assigned to you by'.customers.assigner_id).
Ideally,
Is there any way to do this?
Another option I have considered, is I could do 5-6 different queries pulling the records each from their own table, then use a mysql command to "mesh/interleave" the results from all the queries into one list by chronological order. That would be acceptable too
You could use a UNION query to merge all the information together and use the ORDER BY clause to order the actions chronologically. Each query must have the same number of fields. Your ORDER BY clause should be last.
The examples below assume you have a field called customer_name in the customers table and bonus_amount in the bonuses table.
It would look something like this:
SELECT 'New Customer' as event_type, date,
'New customer was assigned' as title,
CONCAT('New Customer: ', customer_name, ' was assigned') as description
FROM customers
WHERE employee_id = 1
UNION
SELECT 'Bonus' as event_type, date,
'Received a bonue' as title,
CONCAT('Received a bonus of $', FORMAT(bonus_amount, 2), '.') as description
FROM bonuses
WHERE employee_id = 1
UNION
...
ORDER BY date DESC;

Update Calculated [Field] Base on the status of a Separate Table

I need to change the value of a Calculated FIELD depending on the results from a separate table.
I made up a small Fake DB(attached) to highlight my problem..
When the Database is open I want to be able to show on the first screen if ALL training is up to date for each employee, by changing the value of the "Calculated Field".
I have 5 Employees.
Each Employees must do 5(or more) training's.
All Training's must NOT be expired.
If a single training is expired Change Calculated Field Value to "NO GOOD"
If ALL training is NOT expired Change Calculated Field Value to "ALL GOOD"
I have no Idea on how to approach this scenario. Do I need to create a separate "Temp Table" to store this value?
Database found HERE: http://1drv.ms/1tX7L9M
I can't link pictures or more than 2 links yet so please look at these:
http://1drv.ms/1tXhr45
Here is my query.
SELECT Training.ID, Training.EmployeeID, Employees.Name, Training.TrainingID, Training.TrainingDate, TrainingList.Frequency, DateAdd("m",[frequency],[TrainingDate]) AS DueDate
FROM Employees INNER JOIN (Training INNER JOIN TrainingList ON Training.TrainingID = TrainingList.TrainingID) ON Employees.EmployeeID = Training.EmployeeID;
I need to check that all training for each Employee is current. If it is then I need to show this by changing the value from my first form.. The record source of the first form is like this:
SELECT DISTINCTROW Employees.ID, Employees.Name, Employees.EmployeeID, "Help With This Field" AS TrainingStatus
FROM Employees;
The Purpose of this is to make my life easier and be able to see at a glance which employees need to do recurrent training and which are up to date.. I still can't visualized how this can be done.. I am a (Google is my teacher kind of access user :( )
You have a query which computes the DueDate for all training records. Use it as the data source for another query in which you restrict the results to only those records whose DueDate has not already passed.
SELECT tq.*
FROM [Training Query] AS tq
WHERE (((tq.DueDate)>=Date()));
If that query returns the correct records --- only those trainings which have not expired --- reuse its WHERE clause in a GROUP BY query where you count up the number of unexpired trainings per each employee.
SELECT tq.EmployeeID, Count(tq.TrainingID) AS CountOfTrainingID
FROM [Training Query] AS tq
WHERE (((tq.DueDate)>=Date()))
GROUP BY tq.EmployeeID;
If that query also produces sane results, you can use an IIf expression to return "ALL GOOD" when CountOfTrainingID >= 5 and "NO GOOD" when it's < 5.
SELECT
sub.EmployeeID,
sub.CountOfTrainingID,
IIf(
sub.CountOfTrainingID >= 5,
'ALL GOOD',
'NO GOOD'
) AS TrainingStatus
FROM
(
SELECT tq.EmployeeID, Count(tq.TrainingID) AS CountOfTrainingID
FROM [Training Query] AS tq
WHERE (((tq.DueDate)>=Date()))
GROUP BY tq.EmployeeID
) AS sub;
That should get you most of the way to your goal. You would still need to join in the Employees table to get their names.
There may be other issues which you still need to address:
If an employee has not yet completed any trainings, or all his trainings have expired, should his name appear in the query (and form based on that query)?
Is your criteria based on 5 or more different trainings? For example, if an employee completed only the same training 5 times in the past month, should his TrainingStatus be good or no good?