Create filter for most recent date using combined columns - sql

I have created a filtering application in Access that references four simple tables:
Employee: Emp_ID, FirstName, LastName
Skill: Skill_ID, SkillName, SkillDescription, SkillGroup
Employee_Skill: Entry_ID, Emp_ID, Skill_ID, LevelofExperience, Dateupdated
SkillGroupName:SkillGroup_ID SkillGroupName`
Basically the idea of this database is to track employee skills and how the level of experience improves (or not!) over time. The problem I am facing is that I want the application to filter by the most recently updated combination of Skill and Employee. I have found the query that will allow for me to use the two columns as a distinct entity:
SELECT DISTINCT Emp_ID, Skill_ID FROM Employee_Skill
WHERE (SELECT MAX(DateUpdated)From Employee_Skill);
And it works perfectly on its own, but I don't know how to incorporate it either into my main query, which simply joins together the necessary columns for an easier end user experience. It does not visibly show Emp_ID or Skill_ID. It also doesn't in the VBA for the application. (-1 = Include all History; 0 = Only include most updated.)
Update:
I have been able to select the distinct combination of Employee and Skill through my main query by doing this:
SELECT
Employee.FirstName,
Employee.LastName,
Max(Employee_Skill.LevelOfExperience) AS LevelOfExperience,
Skill.SkillName,
Max(Employee_Skill.DateUpdated) AS DateUpdated,
Max(SkillGroup.SkillGroupName) AS SkillGroupName
FROM
SkillGroup INNER JOIN
(Skill INNER JOIN
(Employee INNER JOIN
Employee_Skill ON
Employee.Emp_ID = Employee_Skill.Emp_ID) ON
Skill.Skill_ID = Employee_Skill.Skill_ID) ON
SkillGroup.SkillGroup_ID = Skill.SkillGroup
WHERE
Employee.Active=True
GROUP BY
Employee.FirstName,
Employee.LastName,
Skill.SkillName
ORDER BY
Max(Employee_Skill.LevelOfExperience) DESC;
However, my forms and reports built on this query are stuck with only the option of seeing the most updated version. I am really hoping to have a dynamic form that removes the constraints as desired.

Not sure what you're doing with Max(Employee_Skill.LevelOfExperience) or Max(SkillGroup.SkillGroupName) but I think you need to stick with querying for the detail rows and then include another column marking the Max(Employee_Skill.DateUpdated) filter, like:
SELECT
Employee.FirstName,
Employee.LastName,
Employee_Skill.LevelOfExperience,
Skill.SkillName,
Employee_Skill.DateUpdated,
SkillGroup.SkillGroupName,
iif(max_dateUpdated=dateupdated,1,0) as is_max_DateUpdated
FROM
SkillGroup INNER JOIN
(Skill INNER JOIN
(Employee INNER JOIN
Employee_Skill ON
Employee.Emp_ID = Employee_Skill.Emp_ID) ON
Skill.Skill_ID = Employee_Skill.Skill_ID) ON
SkillGroup.SkillGroup_ID = Skill.SkillGroup inner join
(select
empID,
max(dateupdated) as max_dateUpdated
from
Employee_Skill
group by
empID) mx on
Employee.empID = mx.empID
WHERE
Employee.Active=True

Related

How to obtain all the tuples after a certain date in sql?

I have to obtain the male employee with highest number of requests in the second half of April 2014.
I have these tables:
Employee (EmployeeID, firstName, LastName, gender)
Workplace (CompanyID, EmployeeID, CompanyName)
Extras (ExtraID, CompanyID, Requests, Description, Date)
Extras.Requests is a string, not numerical.
My SQL attempt looks like this:
SELECT
Employee.FirstName, Employee.LastName,
SUM(COUNT(Extras.ExtraID)
FROM
Employee
INNER JOIN
(Workplace
INNER JOIN
Extras ON Workplace.CompanyID = Extras.CompanyID)
ON Workplace.EmployeeID = Employee.EmployeeID
WHERE
Employee.Gender = "male"
AND Extras.Date BETWEEN #4/15/2014# AND #4/30/2014#
SORT BY
SUM(COUNT(Extras.ExtraID) DESC;
LIMIT 1;
I'm not sure if my query is correct or not, thanks in advance.
There are several issues with your querySUM(COUNT(...)) nesting aggregate functions like this isn't permitted
You also need a GROUP BY clause to use aggregation function with non-aggregating columns (which are Employee.FirstName, Employee.LastName in your query).
Sorting is performed by an ORDER BY clause
Your original query includes a nested inner join which is likely to produce unexpected results.
FROM Employee
INNER JOIN(Workplace
INNER JOIN Extras ON Workplace.CompanyID=Extras.CompanyID
) ON Workplace.EmployeeID=Employee.EmployeeID
While nesting joins is allowed it is rarely used, I suggest you avoid it.
I would expect the query to look more like this
SELECT
Employee.FirstName, Employee.LastName, COUNT(Extras.ExtraID)
FROM ((Employee
INNER JOIN Workplace
ON Workplace.EmployeeID = Employee.EmployeeID)
INNER JOIN Extras
ON Workplace.CompanyID = Extras.CompanyID)
WHERE Employee.Gender = "male"
AND Extras.Date BETWEEN #4/15/2014# AND #4/30/2014#
GROUP BY
Employee.FirstName
,Employee.LastName
ORDER BY
COUNT(Extras.ExtraID) DESC;
LIMIT 1;
It's been years since I used access, I think it still wants parentheses in the from clause as I've shown above. In most SQL implementation they are not required, and it is more common for literals to use single quotes e.g. WHERE Employee.Gender = 'male'.

How to retrieve data from multiple tables using Subquery?

Suppose we have two tables
student(studentID, name, department_ID)
department(departmentID, name).
Our aim is to retrieve the data from both tables using the subquery. I'm trying this
select * from department, student
where department.departmentID
IN (select student.departmentID from student, department
where student.departmentID = department.departmentID)
but it returns the cross product of the number of rows of two tables.
This is possible to get the correct result using JOIN like this
select * from department
Inner join student
on student.departmentID = department.departmentID
and using WHERE clause like this
select * from department, student
where department.departmentID = student.departmentID
I'm wondering if someone can tell me how it can be possible using subquery in SQL.
Hope this helps:
select *, (select name from department d where s.departmentID = d.departmentID) as dname
from student s
where (select name from department d where s.departmentID = d.departmentID) is not null
This problem is however meant to be solved using joins. To learn subQ, use proper examples.
SQL Fiddle: Test

How to join two SQL queries into one?

I'm new to SQL and I'm currently trying to learn how to make reports in Visual Studio. I need to make a table, graph and few other things. I decided to do matrix as the last part and now I'm stuck. I write my queries in SQL Server.
I have two tables: Staff (empID, StaffLevel, Surname) and WorkOfArt (artID, name, curator, helpingCurator). In the columns Curator and HelpingCurator I used numbers from empID.
I'd like my matrix to show every empID and the number of paintings where they're acting as a Curator and the number of paintings where they're acting as a Helping Curator (so I want three columns: empID, count(curator), count(helpingCurator).
Select Staff.empID, count(WorkOfArt.Curator) as CuratorTotal
FROM Staff, WorkOfArt
WHERE Staff.empID=WorkOfArt.Curator
and Staff.StaffLevel<7
group by Staff.empID;
Select Staff.empID, count(WorkOfArt.HelpingCurator) as HelpingCuratorTotal
FROM Staff, WorkOfArt
WHERE Staff.empID=WorkOfArt.HelpingCurator
and Staff.StaffLevel<7
group by Staff.empID;
I created those two queries and they work perfectly fine, but I need it in one query.
I tried:
Select Staff.empID, count(WorkOfArt.Curator) as CuratorTotal,
COUNT(WorkOfArt.HelpingCurator) as HelpingCuratorTotal
FROM Staff FULL OUTER JOIN WorkOfArt on Staff.empID=WorkOfArt.Curator
and Staff.empID=WorkOfArt.HelpingCurator
WHERE Staff.StaffLevel<7
group by Staff.empID;
(as well as using left or right outer join)
- this one gives me a table with empID, but in both count columns there are only 0s - and:
Select Staff.empID, count(WorkOfArt.Curator) as CuratorTotal,
COUNT(WorkOfArt.HelpingCurator) as HelpingCuratorTotal
FROM Staff, WorkOfArt
WHERE Staff.empID=WorkOfArt.Curator
and Staff.empID=WorkOfArt.HelpingCurator
and Staff.StaffLevel<7
group by Staff.empID;
And this one gives me just the names of the columns.
I have no idea what to do next. I tried to find the answer in google, but all explanations I found were far more advanced for me, so I couldn't understand them... Could you please help me? Hints are fine as well.
The easiest way to do this is most likely with inner select in the select clause, with something like this:
Select
S.empID,
(select count(*) from WorkOfArt C where C.Curator = S.empID)
as CuratorTotal,
(select count(*) from WorkOfArt H where H.HelpingCurator = S.empID)
as HelpingCuratorTotal
FROM Staff S
WHERE S.StaffLevel<7
group by S.empID;
This way the rows with different role aren't causing problems with the calculation. If the tables are really large or you have a lot of different roles, then most likely more complex query with grouping the items first in the WorkOfArt table might have better performance since this requires reading the rows twice.
From a performance perspective, the following query is probably a little more efficient
select e.EmpId, CuratorForCount, HelpingCuratorForCount
from Staff s
inner join ( select Curator, count(*) as CuratorForCount
from WorkOfArt
group by Curator) mainCurator on s.EmpId = mainCurator.Curator
inner join ( select HelpingCurator, count(*) as HelpingCuratorForCount
from WorkOfArt
group by HelpingCurator) secondaryCurator on s.EmpId = secondaryCurator.HelpingCurator
One method, that can be useful if you want to get more than one value aggregated value from the WorkOfArt table is to pre-aggregate the results:
Select s.empID, COALESCE(woac.cnt, 0) as CuratorTotal,
COALESCE(woahc.cnt) as HelpingCuratorTotal
FROM Staff s LEFT JOIN
(SELECT woa.Curator, COUNT(*) as cnt
FROM WorkOfArt woa
GROUP BY woa.Curator
) woac
ON s.empID = woac.Curator LEFT JOIN
(SELECT woa.HelpingCurator, COUNT(*) as cnt
FROM WorkOfArt woa
GROUP BY woa.HelpingCurator
) woahc
ON s.empID = woahc.HelpingCurator
WHERE s.StaffLevel < 7;
Notice that the aggregation on the outer level is not needed.

Access SQL nesting inner joins

I am new to SQL and am trying to get my head around Access syntax as well as nesting queries. My query is this:
I am attempting to produce: Employee first name, last name and employee id plus project number
I have tables
PROJECT
which has project_name that links to
JOB and project_Number
which also has Employee_id that links to
EMPLOYEE
so I wrote:
SELECT FIRSTNAME, LASTNAME
FROM (EMPLOYEE INNER JOIN JOB ON EMPLOYEE.EMPLOYEE_ID=JOB.EMPLOYEE_ID)
INNER JOIN PROJECT ON PROJECT.PROJ_NAME=JOB.PROJ_NAME
(SELECT PROJECT_NO
FROM PROJECT);
Based on what you're saying, this should work. However, I'd guess that project and job are related based on project_id and not project_name. Also, what the context of your question states (project_name) differs from your sample query (proj_name), so I'm going with your sample query. If you show a schema, we can help better.
SELECT employee.FIRSTNAME, employee.LASTNAME, project.PROJECT_NO
FROM
(
EMPLOYEE
INNER JOIN
JOB
ON EMPLOYEE.EMPLOYEE_ID = JOB.EMPLOYEE_ID
)
INNER JOIN
PROJECT
ON PROJECT.PROJ_NAME = JOB.PROJ_NAME

Three tables join given me the all combination of records

When i written the query like the following.. It's written the combination of all the records.
What's the mistake in the query?
SELECT ven.vendor_code, add.address1
FROM vendor ven INNER JOIN employee emp
ON ven.emp_fk = emp.id
INNER JOIN address add
ON add.emp_name = emp.emp_name;
Using inner join, you've to put all the links (relations) between two tables in the ON clause.
Assuming the relations are good, you may test the following queries to see if they really make the combination of all records:
SELECT count(*)
from vendor ven
inner join employee emp on ven.emp_fk = emp.id
inner join address add on add.emp_name = emp.emp_name;
SELECT count(*)
add.address1
from vendor ven, employee emp, address add
If both queries return the same result (which I doubt), you really have what you say.
If not, as I assume, maybe you are missing a relation or a restriction to filter the number of results.