Combining Queries that require three tables SQL Query - mysql

I'm finding it a bit confusing to solve the following questions...
"
An employee may be assigned to more than one project and a project may have many employees. Consider the following relational schema and write SQL statements for the below queries.
Employees (empID, empName, empDOB, empAddress, salary, deptID, jobID)
Assignments (empID, projID, assignedDate, completionDate, status)`
Projects (projID, projDescription, startDate, endDate, projType)
(a) Display the names of employees who were born before 31st Jan 1980 and assigned a ‘Office Complex’ type project, sort results in ascending order of name.
(b) Retrieve the empIDs who are assigned at least two (2) projects.
"
My answer so far .
(a) SELECT empName FROM EMPLOYEES WHERE empDOB < '31-january-1980' AND ....
"
Please help me out

try this :
A)
SELECT employee.empName
FROM Assignments ass
JOIN Employees employee
ON employee .empID= ass.empID
JOIN Projects project
ON project.projID= ass .projID
WHERE employee.empDOB < '31-january-1980'
AND project.projType = ‘Office Complex’
ORDER BY employee.empName;
Without using JOIN CLAUSE
SELECT DISTINCT employee.empName
FROM Employees employee
WHERE employee.empDOB < '31-january-1980'
AND employee.empID IN (
SELECT ass.empID
FROM Assignments ass
WHERE ass.projID IN (
SELECT project.projID
FROM Projects project
WHERE project.projType = ‘Office Complex’
)
)
ORDER BY employee.empName ASC;
b)
SELECT ass.empID, COUNT(*) as counting
FROM Assignments ass
GROUP BY ass.empID
HAVING COUNT(*) >= 2;

Related

Trying to get a row count in a subquery

I have two tables, one is departments and the other is employees. The department id is a foreign key in the employees table. The employee table has a name and a flag saying if the person is part-time. I can have zero or more employees in a department. I'm trying to figure out out to get a list of all departments where a department has at least one employee and if it does have at least one employee, that all the employees are part time. I think this has to be some kind of subquery to get this. Here's what I have so far:
SELECT dept.name
,dept.id
,employee.deptid
,count(employee.is_parttime)
FROM employee
,dept
WHERE dept.id = employee.deptid
AND employee.is_parttime = 1
GROUP BY employee.is_parttime
I would really appreciate any help at this point.
You must join (properly) the tables and group by department with a condition in the HAVING clause:
select d.name, d.id, count(e.id) total
from dept d inner join employee e
on d.id = e.deptid
group by d.name, d.id
having total = sum(e.is_parttime)
The inner join returns only departments with at least 1 employee.
The column is_parttime (I guess) is a flag with values 0 or 1 so by summing it the result is the number of employees that are part time in the department and this number is compared to the total number of employees of the department.
As a preliminary aside, I recommend expressing joins with the JOIN keyword, and segregating join conditions from filter conditions. Doing so would make the original query look like so:
select dept.name, dept.id, employee.deptid, count(employee.is_parttime)
from employee
join dept on dept.id = employee.deptid
where employee.is_parttime = 1
group by employee.is_parttime
It doesn't make much practical difference for inner joins, but it does make the structure of the data and the logic of the query a bit clearer. On the other hand, it does make a difference for outer joins, and there is value in consistency.
As for the actual question, yes, one can rewrite the original query using a subquery or an inline view to produce the requested result. (An "inline view" is technically what one should call an embedded query used as a table in the FROM clause, but some people lump these in with subqueries.)
Example using a subquery
select dept.name, dept.id
from dept
where dept.id in (
select deptid
from employee
group by deptid
having count(*) == sum(is_parttime)
)
Example using an inline view
select dept.name, dept.id
from dept
join (
select deptid
from employee
group by deptid
having count(*) == sum(is_parttime)
) pt_dept
on dept.id = pt_dept.deptid
In each case, the subquery / inline view does most of the work. It aggregates employees by department, then filters the groups (HAVING clause) to select only those in which the part-time employee count is the same as the total count. Naturally, departments without any employees will not be represented. If a list of department IDs would suffice for a list of departments, then that's actually all you need. To get the department names too, however, you need to combine that with data from the dept table, as demonstrated in the two example queries.

aggregate function 'count' not returning expected results

I am using mySQL to query a mock university database. This is for a class so. The query I am trying to make is to this question:
Find the names and ids of the students who have taken exactly one
course in the Spring 2010 semester.
schema tables:
student(id, name, dept_name, total_cred)
takes(id, course_id, sec_id, semester, year, grade)
I can query the schema for all students who took classes in Spring of 2010 no problem. But where I run into trouble is the 'exactly one class' part.
select distinct s.id, name
from student s join takes
where semester = 'Spring' and
year = 2010;
I thought I would use a set operator like not in to compare that result to another that returns the number of classes taken by each student:
select distinct count(s.id) num_classes, name
from student s join takes
where semester = 'Spring' and
year = 2010
group by name
The problem is that when I run this query it returns the count of 8 for each name. But I have no idea where it is getting that number because there is nothing that occurs exactly 8 times.
My question(s):
1) am I going about this the right way?
2) If so what am I doing wrong to make the count return that way?
Try this:
select s.id, s.name
from student s join takes t on s.id = t.id
where t.semester = 'Spring' and
t.year = 2010
group by s.id, s.name
having count(*) = 1

Get the first and last names of all employees who entered the project at the same time as at least one other employee

Question:
Get the first and last names of all employees who entered the project at the same time as at least one other employee.
I have four tables Employee, Department, Project, Works_on as shown in below.
I tried the query:
SELECT
emp_fname,
emp_lname
FROM employee a,
works_on b
WHERE a.empno=b.empno;
Please let me know what is wrong with what I am doing?
for this you need to use both Employee (emp_no,emp_fname,emp_lname) and Works_on (emp_no, Enter_date) relationship linked through emp_no on both tables.
in your query you just used Employee table which does not have connection with checking project submitted times.
You can use either of the below query to get the desired results. I have used partition by clause to group related data.
WITH QUERY1 AS (
SELECT EMP_NO,ENTER_DATE, COUNT(*) OVER (PARTITION BY ENTER_DATE ORDER BY EMP_NO ) "t" FROM works_on)
select t2.emp_fname, t2.emp_lname from query1 t1 inner join employee t2 on t1.emp_no=t2.emp_no where "t">1;
select emp_fname, emp_lname from employee where emp_no in (
SELECT EMP_NO FROM (
SELECT EMP_NO,ENTER_DATE, COUNT(*) OVER (PARTITION BY ENTER_DATE ORDER BY EMP_NO ) "t" FROM works_on
) query1 where query1."t">1);
First of all your query will return employee names who ever worked on any project, and better you would use INNER JOIN.
If I understand right; you want employee who work on the same project (let's say ProjectX) and again the employee who entered ProjectX on same time and also there must be at least 2 employee having the same time on ProjectX.
If I am correct with the above:
You need to group your data. For instance first group projects that have at least 2 same enter_date like
SELECT Project_no, Enter_date FROM Works_on having Count(emp_no)>=2
This will give you all projects and dates that have employee more or equal than 2. Now we can find employee that worked on these projects at these dates.
SELECT emp_fname, emp_lname FROM Employee INNER JOIN Works_on AS WO ON WO.emp_no=Employee.emp_no
INNER JOIN
(
SELECT Project_no, Enter_date FROM Works_on having Count(emp_no)>=2
) AS PWith2MoreEmployee
ON PWith2MoreEmployee.Project_no=WO.Project_no
AND
PWith2MoreEmployee.Enter_date=WO.Enter_date
I hope this will give you what you are looking for.

mySql Subquery Answers Check Final Exam Questions

I'm having some doubts regarding these answers of mine, would greatly appreciate if you guys can clarify if im right or wrong,
Questions:
An employee may be assigned to more than one project and a project may have many employees. Consider the following relational schema and write SQL statements for the below queries.
Employees (empID, empName, empDOB, empAddress, salary, deptID, jobID)
Assignments (empID, projID, assignedDate, completionDate, status)
Projects (projID, projDescription, startDate, endDate, projType)
(a) Display the names of employees who were born before 31st Jan 1980 and assigned a ‘Office Complex’ type project, sort results in ascending order of name. (5 marks)
(b) Retrieve the empIDs who are assigned at least two (2) projects. (5 marks)
Answers:
(a) SELECT empName FROM Employees WHERE empDOB < '31-01-1980' AND projType = (SELECT projType FROM Projects WHERE projType = 'Office Complex') ORDER BY empName;
(b) SELECT empID FROM Employees GROUP BY (SELECT projID From Projects) HAVING COUNT(*)>1 ORDER BY empID;
I feel the answer for the second question may be wrong.
For part a), I'd join the tables to match up employees with the project type:
SELECT empName
FROM Employees
INNER JOIN Assignments ON Assignments.empID = Employees.empID
INNER JOIN Projects ON Assignments.projID = Projects.projID
WHERE empDOB < 31-01-1980 AND projType = 'Office Complex'
ORDER BY empName;
As it stands, your statement attempts to find projType = 'Office Complex' in the Employee table, where it doesn't exist.
For the second question, everything you need is in the Assignments table:
SELECT empID, COUNT(projID)
FROM Assignments
GROUP BY empID
HAVING COUNT(projID) > 1

MySQL - Group By SUM with two tables

I'm using MySQL 5.1 and I have two tables, projects and employee. There is a foreign key in employee (number_project) that is the primary key of projects(code_project).
---> Exactly: SQL Fiddle
I'm trying get the SUM of the projects by department with this query:
SELECT emp.department_emp AS Department, SUM( pro.price ) AS total_department
FROM employee AS emp, projects AS pro
WHERE emp.number_project = pro.code_project
GROUP BY emp.department_emp
It returns:
DEPARTMENT TOTAL_DEPARTMENTA
Accounting 2600
IT 4200
But It should returns:
DEPARTMENT TOTAL_DEPARTMENT
Accounting 1300
IT 4200
The problem is that when the query sums the same projects many times as employees of the same department are working in that project.
Thanks!
Use a subquery to create a list of unique (department, project) combinations:
select e.department_emp
, sum(p.price)
from (
select distinct department_emp
, number_project
from Employee
) e
join Projects p
on p.code_project = e.number_project
group by
e.department_emp
Working example at SQL Fiddle.
Your database could use some serious work. Employee to project should be a many-to-many relation, not a many-to-one relation. And a field called "number" should not be called "code" in another table.
You can use a subquery that "collapses" the employees, arbitrarily choosing the department of one employee from the project:
SELECT department,
SUM(price) AS total_department
FROM ( SELECT project.code_project AS project,
project.price AS price,
MIN(employee.department_emp) AS department
FROM project
JOIN employee
ON project.code_project = employee.number_project
GROUP
BY project.code_project,
project.price
)
GROUP
BY department
;
(Naturally, this will give misleading results if a single project has employees from multiple different departments, because it will assign the entire price of the project to one of those departments.)
SELECT emp.department_emp AS Department, SUM( pro.price ) AS total_department
FROM(SELECT DISTINCT *
FROM employee AS emp, projects AS pro
WHERE emp.number_project = pro.code_project
) AS P
GROUP BY emp.department_emp