Can you explain these 2 SQL queries to me? - mysql

I'm studying for my DB exam which covers a lot of SQL statements I need to write by hand. Below is the schema diagram and solutions for 2 scenarios that were outlined in my book that don't seem to make sense to me.
Q13: Retrieve the names of all employees in department 5 who work more than 10 hours per week on the ProductX project.
SELECT FNAME, LNAME
FROM EMPLOYEE,PROJECT, WORKS_ON
WHERE DNO = 5 AND PNAME = ‘PRODUCT X’ AND HOURS>10 AND ESSN=SSN;
Shouldn't the WHERE clause include PNO = NUMBER ? How would the WORKS_ON table know to reference the PROJECT table without including this? Is it because we reference the ESSN = SSN?
Q1: Retrieve the name of each employee who has a dependent with the same first name and is the same sex as the employee.
SELECT E.FNAME, E.LNAME
FROM EMPLOYEE AS E
WHERE E.SSN IN (SELECT D.ESSN FROM DEPENDENT AS D WHERE E.FNAME = D.DEPENDENT_NAME AND D.SEX = E.SEX);
I understand this query all the way up until the WHERE clause. I don't understand what E.SSN IN is trying to do with the sub query ahead of it. If someone can explain this, that would be great.

For the first question, yes you guessed it right. There should be another clause as PNO = NUMBER.
For second question, think of it this way: Select an employee where employee number[Ssn] is in the list of employeeIDs [Essn] returned by sub-query for each given employee number [Ssn]. This should work fine. But, because Essn and Dependant Name are both keys for the Dependent table, you can also use simple join statements and get it done. Read about it here: http://www.w3schools.com/sql/sql_join.asp

For Q13: You need to include one more condition in WHERE clause that tells the relation between Works_on and Project, which is
SELECT FNAME, LNAME
FROM EMPLOYEE,PROJECT, WORKS_ON
WHERE Pno = Pnumber AND DNO = 5 AND PNAME = ‘PRODUCT X’ AND HOURS>10 AND ESSN=SSN;
Q1: uses correlated sub-query.

SELECT E.FNAME, E.LNAME
FROM EMPLOYEE E
INNER JOIN WORKS_ON WO
ON WO.Essn = E.Ssn
INNER JOIN PROJECT P
ON P.Pnumber = WO.Pno
where E.DNO = 5
and P.name = 'ProductX'
and WO.Hours > 10

Related

SQL iterative loop to see if employee works on all projects

The query I am supposed to form has to accomplish the following task:
Retrieve the names of all employees who work on every project.
I currently have three tables. The Employee, works_on, and project tables. The goal to accomplish this query is to get each project id from the project table, compare it to the project id in the works_on table. When there is a match it will get the SSN and get the names from the employee table. The query I have formed is this:
SELECT e.Fname, e.Minit, e.Lname, p.Pname
FROM EMPLOYEE e, PROJECT p, WORKS_ON w
WHERE p.Pnumber=w.Pno AND w.Essn=e.Ssn
But this outputs All the employees that work on each project not all the employees that work on EVERY project. Is there some way to iterate through a list of results from the query SELECT Pnumber FROM PROJECT?
I really hope I worded this question clearly for your understanding.
Also you don't need PROJECT, WORKS_ON is sufficient.
HAVING filters the results after a GROUP BY.
The GROUP BY e.Ssn means that the COUNT(*) in HAVING is per employee. The JOIN ON WORKS_ON is mapping the user to PROJECT giving the count.
Use JOIN table tbl ON .. = tbl.id JOIN syntax - easier to read.
SELECT e.Fname, e.Minit, e.Lname
FROM EMPLOYEE e
JOIN WORKS_ON w
ON w.Essn=e.Ssn
GROUP BY e.Ssn
HAVING COUNT(*) = (SELECT COUNT(*) FROM PROJECTS)
SELECT e.Fname, e.Minit, e.Lname
FROM EMPLOYEE e
WHERE NOT EXISTS(SELECT PNum
FROM PROJECT
WHERE NOT EXISTS(SELECT *
FROM WORKS_ON
WHERE PNum=PNo AND Essn=e.ssn));
You can select the employee on the condition that:
There doesn't exist a project where the employee doesn't work on it.
You can use the innermost nested query to select tuples where there doesn't exist a WORKS_ON tuple where employee with Ssn works on project with Pnum.
Then use the outermost nested query to select the tuples where the above condition doesn't hold ^^ (so there is an employee with Ssn that works on project with Pnum) for ALL projects.
I hope that makes sense and good luck!

How to get records by using 3 tables or work with 3 tables?

I have been asked this question in an interview. I have tried so hard, but unfortunately was not able to get it right.can anybody help me with this?
Retrieve the last name, first name, dept name of that employee using these tables.I am writing down the tables and columns.however, i am not writing that dummy data.
Employee- (id, last name, first name, DOB, SSN) and some other columns(not useful).
Dept - (D_id, dept name)
Emp_Dept - (id, D_id)
You can try this solution for your problem :
Query :
SELECT E.last_name, E.first_name, D.dept_name
FROM Employee AS E
-- Get employee dept
INNER JOIN Emp_Dept AS ED
ON ED.id = E.id
-- get dept data
INNER JOIN Dept AS D
ON D.id = ED.D_id
I hope it will help you.
But this query doesn't return value of employee without dept. If this is necessary you should use LEFT JOIN instead of INNER JOIN

SQL Complex Query w/ Inner Join

I have 2 tables, 1 called Employee and 1 called Salary. Employee table consists of Emp_Name, Emp_Address, Emp_ID & Salary table consists of Salary_Details and Emp_ID. > Can you write down a query for retrieving the Salary_Details of 1 of the employee based on last name using Inner Join?
I am not sure what you are looking for, but this might help you:
SELECT * FROM Employee e
INNER JOIN Salary s ON e.Emp_ID = s.Emp_ID
WHERE e.Emp_Name = 'EMPLOYEENAME'
That will give you back all fields from Employee and Salary for an Employee with the name = 'EMPLOYEENAME' (which you can exchange then).
You can adjust the columns returned as needed depending on your app...
SELECT e.Emp_Name, e.Emp_ID, s.Salary_Details
FROM Employee e
INNER JOIN Salary s USING (Emp_ID)
WHERE e.Emp_Name = 'Smith';
The USING keyword is kind of obscure and works only if the join column is named identically in both tables. The previous answer with ON instead of USING will work in all cases. I like USING as a personal preference.

SQl query Multiple select statments in the same table under different conditions

So I have 3 tables that I want to perform some queries on but during that process I end up returning back to a table I already performed some functions on and it.
I first get the essn from one dependent table and search the employee table for a ssn matching it then i got the superssn and compare to the mgrssn in another table. The last step is to go back into the employee table and find the name of the person who has the same ssn of mgrssn.
The issue here is that once i get the matching superssn I can't access the other rows.
select lname, fname from
(select mgrssn from department) as d,
(select superssn, lname,fname,ssn from
(select essn from dependent where dependent_name ='joy') as de,
(select ssn,lname,fname,superssn from employee) as e
where essn =ssn) as s
where s.ssn = mgrssn
Should I look into doing joins instead?
You don't need the subqueries. Your query is a bit hard to follow (you don't have table aliases for all the columns), but I think this is what you are trying to do:
select lname, fname
from department d join
employee e
on e.ssn = d.mgrssn join
dependent dep
on dep.essn = e.ssn
where dep.dependent_name ='joy';
Simple rule: Never use commas in the from clause. Always use explicit join syntax.

When to use an identifier in SQL queries

I have just been looking at some example database queries, and came across this :
Find the identifier, name & address of employees of the Research department.
Method I: Join Method
SELECT Ssn, FName, LName, Address
FROM EMPLOYEE, DEPARTMENT
WHERE Dno = Dnumber
AND Dname = ‘Research’
Method II: Subquery Method
SELECT Ssn, FName, LName, Address
FROM EMPLOYEE
WHERE Dno IN
( SELECT Dnumber
FROM DEPARTMENT
WHERE Dname = ‘Research’ );
In these examples, why can you not leave out the Dno = Dnumber line? How do you know when to include this?
John, you are using implicit join syntax cf ansi SQL '89.
WHERE JOIN
SELECT Ssn, FName, LName, Address
FROM EMPLOYEE, DEPARTMENT
WHERE Dno = Dnumber
AND Dname = 'Research'
You should never ever use that because it is confusing as hell.
And it causes a lot of errors because it does a cross join if you're not careful.
The following syntax using explicit joins cf ANSI SQL '92 which is much clearer.
SELECT Ssn, FName, LName, Address
FROM EMPLOYEE
inner join DEPARTMENT on (employee.dnumber = department.dno)
WHERE Dname = 'Research'
This also answers why you cannot leave out the dnumber = dno, because that's the join condition
SUBQUERY
A subquery is really a join by other means.
In general you should avoid a subquery because a join is faster (90% of the time)
Some people find subqueries easier to understand. I would say that if you don't grok joins stay away from SQL!
Still sometimes you're doing something to complex or bizarre for a join and then the subquery is an option.
Back to your question: because the subquery is really a join by other means you need that join condition to make the join :-).
I would actually write something like this.
SELECT
Ssn, FName, LName, Address
FROM
EMPLOYEE
LEFT JOIN
DEPARTMENT ON EMPLOYEE.Dno = DEPARTMENT.Dnumber
WHERE
Dname = "Research"
The Dno = Dnumber is used to bridge the JOIN between the Employee and Department tables. You need it to identify the relationship between tables you are joining.
There are many ways to write JOIN statements.
This is a good tutorial about joins - http://mysqljoin.com/
Each employee belongs to a department. Dno = Dnumber is what defines the relationship between the two. So you have to keep that relationship in your join. Dname = 'Research' further filters to only include Research department employees.
Should you not join Dno to Dnumber, you will wind up with a Cartesian product.
The "Dno = Dnumber" line is the join clause - it tells the query only to include records in the employee table whose Dno matches the department number in the department table.
You use the Dno = Dnumber line to basically create JOIN criteria.
If you didn't use them you'd have a full JOIN
However, I would contend that the correct way to do the JOIN is to actually do
SELECT
EMPLOYEE.[Ssn]
, EMPLOYEE.[FName]
, EMPLOYEE.[LName]
, EMPLOYEE.[Address]
FROM
EMPLOYEE
JOIN
DEPARTMENT
ON DEPARTMENT.[Dnumber] = EMPLOYEE.[Dno]
WHERE
DEPARTMENT.[Dname] = 'Research'
The Dno = Dnumber clause is needed for you to join the two tables. Without this, you'll get what's called a Cartesian join, where you'll get n x m number of rows returned, where n = # rows in the EMPLOYEE table, and m = # rows in the DEPARTMENT table.
You can find a good tutorial on SQL join at http://www.1keydata.com/sql/sqljoins.html.