I have 2 tables (with different fields) :
tbl_Report (UIN, GID, RDate, RTS_a) > (UIN = unique nr.)
tbl_Employee (GID, Sname, Gname, Org_Cd) > (GID = Unique 8 char string)
the link is 1 to many based on GID
tbl_Report: every Employee (GID) generates monthly one or more reports (RTS_a = SR, IR or OR) of each type
I want to create 2 queries:
(1) for all Employees, so that I can see which employee delivered how many reports of specified type
in each month, even if Employee didn't enter a report at all..
RTS_a WHERE [ enter a Vald RTS_a]
Year([Rdate]) Where [enter Year]
(2) an overview for employees (selected by Report-type RTS_a) who didn't
deliver a report vor a given year (Rdate)
RTS_a WHERE [ enter a Vald RTS_a]
Year([Rdate]) Where [enter Year]
the problem is I don't know how to get also the employees in it, who didn't entered data at all...
I've tried in Query criteria under RTS_a : [enter a Valid RTS_a] ""or [enter a Valid RTS_a] Is Null
but that doesn't seem to work
(& somehow things went wrng when I tried using :
WHERE NOT IN an WHERE NOT EXISTS)
as a non native English speaking Access beginner... (and totally lost...)
I could use some help on this....
You got to use an outer join. In your query, in design mode, you should have both tables, and have a link between tbl_Employee.GID and tbl_Report.GID.
Double click the link (or right click and select Join Properties) and then click option 2 or 3 (the one saying you want ALL Employees and matching Reports.
Edit: for point(2), you have to make a query for those who DID enter data in [Enter Year], then make anther query, "outer joining" Employees and EmployeesWithoutDataInYearX WHERE EmployeesWithoutDataInYearX.employeeId is Null
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm working on a database for work, and I need to figure out a way for Access to count the number of projects that each employee is assigned. Projects have 1 or 2 employees assigned, and my boss needs to be able to quickly figure out how many projects each person is working on. Below is an example table:
Project Employee 1 Employee 2
Project A John Doe Jane Doe
Project B Jane Doe Sam Smith
Project C Jane Doe John Doe
Project D Sam Smith Anna Smith
Project E Anna Smith John Doe
And here is the result I'm looking for:
**Employee # of Projects**
John Doe 3
Jane Doe 3
Sam Smith 2
Anna Smith 2
The table you described is probably not the best way to store the data and I think it's only making your job more difficult. The value of a relational database is that you can have data living in different tables but related based on primary/ foreign keys which makes it significantly easier to pull reports like the one you described. It seems to me like this table might have previously lived in Excel, and I would spend some time now establishing relationships in Access which will save you time and headaches later. I would suggest creating 3 separate tables: employees, projects, and project employee assignments.
The employee table should have 3 fields: EmployeeID, which should be set to AutoNumber in Design view and then selected as the primary key, First Name, and Last Name, both short text fields. This EmployeeID field will be referenced in the project employee assignments table.
The projects table should have 2 fields: ProjectID, also set to AutoNumber in Design view and selected as the primary key, and ProjectName which will also be a short text field. You can also add other fields, perhaps a text field for ProjectDescription would be helpful later on.
The Project-Employee Assignments table should have 2 fields: EmployeeID and ProjectID. If you aren't familiar with one-to-one, one-to-many, and many-to-many relationships I would suggest looking it up- you are describing a many-to-many relationship between the projects and employees, that is, one project can have many employees and one employee can be involved in many projects. This table exists to establish those relationships between employees and projects.
From here, go to the database tools tab and select Relationships. You'll need to establish a one-to-many relationship between the Employees table and the Assignments table on the EmployeeID field. You'll also need to establish a one-to-many relationship between the Projects table and the Project-Employee Assignments table on the ProjectID field.
Enter each relationship between projects and employees in the Assignments table. If you have a short list of projects and employees, you can do this directly in the table, but I'd suggest creating a form to do this with 2 combo boxes that each select from the lists of existing projects and employees, respectively. There are many tutorials about creating combo boxes that show informative columns, like employee name, but save the ID numbers to the table. Search "Bind Combo Box to Primary Key but display a Description field" for one example.
Finally, create a query to count projects per employee. You should include your Employees table, as well as your Project-Employee Assignments table. Select FirstName and LastName from the Employees table. Select both columns (EmployeeID and ProjectID) from the Project-Employee Assignments table. Unclick "show" for EmployeeID. Right-click anywhere in the query to get a menu of more options and click the sigma for totals. Set the total for EmployeeID, FirstName, and LastName to "Group By" and for ProjectID to "Count" then save the query. Run the query and enjoy having your totals!
Elizabeth Ham's answer is very thorough and I recommend following her advice, but knowing that sometimes we don't have time to do a complete overhaul, here's some instructions on how to get results from the given table structure. As Elizabeth and I pointed out (in my comment), a single query could have gotten the requested data if the tables were complete and properly normalized.
Because there are multiple employee columns for which you want statistics, you need to join the given table at least twice, each time grouping on a different column and using a different alias. It is possible to do this using the visual Design View, however it is usually easier to post questions and answers on StackOverflow using SQL text, so that's what follows. Just paste the following code into the SQL view of a query, then you should be able to switch between SQL view and Design View.
Save the following SQL statements as two separate, named queries: [ProjectCount1] and [ProjectCount2]. Saving them allows you to refer to these queries multiple times in other queries (without embedding redundant subqueries):
SELECT P.[Employee 1] As Employee, Count(P.Project]) As ProjectCount
FROM Project As P
GROUP BY P.[Employee 1];
SELECT P.[Employee 2] As Employee, Count(P.[Project]) As ProjectCount
FROM Project As P
GROUP BY P.[Employee 2];
Now create a UNION query for the purpose of creating a unique list of employees from the two source columns. The UNION will automatically keep only distinct values (i.e. remove duplicates). (By the way, UNION ALL would return all rows from both tables including duplicates.) Save this query as [Employees]:
SELECT Employee FROM [ProjectCount1]
UNION
SELECT Employee FROM [ProjectCount2]
Finally, combine them all into a list of unique employees with a total sum of projects for each:
SELECT
E.Employee As Employee, nz(PC1.ProjectCount, 0) + nz(PC2.ProjectCount, 0) As ProjectCount
FROM
([Employees] AS E LEFT JOIN [ProjectCount1] As PC1
ON E.[Employee] = PC1.[Employee])
LEFT JOIN [ProjectCount2] As PC2
ON E.[Employee] = PC2.Employee
ORDER BY E.[Employee]
Note 1: The function nz() converts null values to the given non-null value, in this case 0 (zero). This ensures that you'll get a valid sum even when an employee appears in only one column (and as such has a null value in the other column).
Note 2: This solution will double count an employee if it's listed as both [Employee 1] and [Employee 2] in the original table. I assume that there are proper constraints to exclude that case, but if needed, one could do a self join on the second query [ProjectCount2] to exclude such double entries.
Note 3: If you do decide to follow Elizabeth's advice and you already have a lot of data in the existing structure, the above queries can also be useful in generating data for the new, normalized table structure. For instance, you could insert the unique list of employees from the above UNION query directly into a newly normalized [Employee] table.
I have a Database, my query is related to 2 tables (ms_recepciones & ms_estados). This database is to Manage a Mobile Repair Store.
Tabla > ms_recepciones
Tabla > ms_estados
A record in ms_recepciones, may have different states. These states are stored in a history in ms_estados. For example: admitted, budgeted, invoiced, canceled...
They are related by the key id_recepcion
[?] My question is:
I need to display all the data of the ms_recepciones and the status has to be only the last registered in ms_estados.
For example:
If the id_recepcion #50 of ms_recepciones has had the states -> admitted, delivered, invoiced. It will show only invoiced (because it's the last.).
The same with all the other receptions to be shown in a single table together.
Later I hope to filter: current state -> invoiced, admitted, etc.
In advance, thank you very much for your help. 4 people we tried to do it, without success.
SELECT
r.id_recepcion, coalesce(max(e.fecha_estado), '0000-00-00 00:00:00') as UltFecha, e.id_estado, e.estado
FROM
ms_estados e
INNER JOIN
ms_recepciones r
ON
r.id_recepcion = e.id_recepcion
GROUP BY
e.id_recepcion
This code I tried, but the first row is incorrect.
Regards.
The problem is that your COALESCE clause will give you the latest date, but e.id_estado and e.estado will not necessarily give you the matching columns to that latest row.
You are not the first person to have this issue. See the answers to this question: Optimize sub-query selecting last record of each group.
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;
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?
Working with MS Access for the first time and coming across a few problems if someone could please point me in the right direction.
So I'm doing a mock database (so it looks silly) just to learn the ins and outs and need some help with DLookUp at the moment.
My database has two tables, with the following fields:
C_ID the PK in Courses and FK in Student
tblCourse: C_ID, Title, Subject
tblStudent: S_ID, C_ID, Name, EnrollDATE
As I said this is just for testing/learning. So what I want is to have a filter that gives me a list of C_ID's based on which EnrollDates are NULL.
so filter is:
Expr1: DLookUp("[tblStudent]![C_ID]","tblStudent","isNull([tblStudent]![EnrollDATE])")
I have also tried with the criteria being
[tblStudent]![EnrollDATE] = Null
Currently I get just blank fields returned. Any help is greatly appreciated, and please ask me to elaborate if my explanation is off.
Thank You!
The correct syntax looks like this:
DLookup("C_ID", "tblStudent", "EnrollDate is null")
You don't need to include the table name when you specify the columns
In Access, you check for Null by using xxx is null or xxx is not null
Note that DLookup only returns one value (if the criteria matches more than one row, the value is taken from any row), so you can't use it to get a list of C_IDs back.
EDIT:
What you actually want to do is select data from one table, and filter that based on data from the other table, correct?
Like, selecting all courses where at least one student has an empty EnrollDATE?
If yes, you don't need the DLookup at all, there are two different ways how to do that:
1) With a sub-select:
select *
from tblCourse
where C_ID in
(
select C_ID
from tblStudents
where EnrollDATE is null
)
2) By joining the tables:
select tblCourse.*
from tblCourse
inner join tblStudent on tblCourse.C_ID = tblStudent.C_ID
where tblStudent.EnrollDATE is null
This is SQL, so you need to switch to SQL View in your query in Access.