How to select departments with no female employees - sql

The schema is as follows:
Employee: Fname, Lname, Ssn, Sex, Dno
Department: Dname, Dnumber, Mgr_ssn
Dnumber is the primary key of department, Ssn is the primary key of employee.
Dno is a foreign key referencing Dnumber.
I tried approaching the problem with this query:
SELECT Dnumber, count(ssn) from DEPARTMENT
INNER JOIN Employee
ON Dno = Dnumber
WHERE sex = ALL('M')
GROUP BY Dnumber
I thought the use of ALL would select only departments with all male employees, where the count would then be applied, however it is selecting all departments with male employees and then counting them.
I'm on the right tracks, and seems like I'm overlooking something trivial, but have tried looking up similar questions but have found no information.
Any pointers toward similar questions or advice on where i'm misstepping would be great.

This just screams "not exists":
select d.*
from department d
where not exists (select 1 from employee where d.dnumber = e.dno and d.sex = 'F');
Incidentally, assuming that all non-females are male would not work in many databases.
Your have multiple missteps in your query. First, ALL() applies to the list of values in the subquery. It doesn't have anything to do with the outer query. Second, it is filtering out all the females in the WHERE. That is fine if you want to count the numbers, but it give you nothing to determine if there are any females.

You could use HAVING (assuming that e.sex is defined as NOT NULL):
SELECT d.dnumber, d.dname
FROM department d
JOIN employee e
ON e.dno = d.dnumber
GROUP BY d.dnumber, d.name
HAVING COUNT(CASE WHEN e.sex = 'F' THEN 1 END) = 0;

Related

List the last name, salary, and department name of all employees who work on the ‘Computerization’ project

SELECT Lname, Salary, Dname
FROM EMPLOYEE
INNER JOIN DEPARTMENT ON DNO = DNUMBER
INNER JOIN WORKS_ON ON SSN = ESSN
INNER JOIN PROJECT ON PNUMBER = PNO
WHERE PNAME='COMPUTERIZATION'
I tried this but it shows no output. Not sure where exactly I'm wrong.
Link to db:
https://www.db-fiddle.com/f/xhEj2sAgdTMABBkCtJvmoC/0#&togetherjs=Dv0FGDGziv
Your Postgres is configured for case-sensitive comparison. So, you need to use the exact string:
where p.pname = 'Computerization'
I strongly encourage you to use table aliases and qualified column names as well.

SQL select with multiple different conditions

I am still learning SQL and can't find a proper way to find the following information:
I have created a table "employees" with the following columns:
'department', 'age', 'salary', 'bonus';
I am trying to design a query that will give me all employees that have someone the same age as them in another department and with a bonus superior to their salary.
(to be more precise, if someone in department 'SALES' has the same age as someone in department 'RESEARCH' and have a bonus that is superior to that guy in research's salary, then I would like to display both of them)
Is this possible to do in sql?
Thank you for your time,
-Tom
You can do this using exists. Because you care about the relationship in both direction, this is as simple as looking for people with the same age in the two departments but who do not have the same bonus:
select e.*
from employees e
where exists (select 1
from employees e2
where e2.department <> e.department and e2.age = e.age and
e2.bonus <> e.bonus
);
To get the pairs on the same row, use a self-join:
select e1.*, e2.*
from employees e1 join
employees e2
on e1.age = e2.age and e1.department <> e2.department and
e1.bonus > e2.bonus;

How to join two SELECT statements operating on the same column on a single table with different conditions?

I am trying complete the following exercise
Create a query that has the employee name, supervisor name, and employee salary for each employee who works in the 'Research' department
Which operates on the following schema:
https://scontent-lht6-1.xx.fbcdn.net/v/t34.0-12/23140228_10214571052854224_1441212020_n.png?oh=15f361ec2679373f2cfeb427dd5b6978&oe=59F9593B
I have developed the following query which works somewhat, but does not match the rows accordingly so I end up with a result consisting of the employee names and salaries, with separate rows for the manager names. My query is as follows:
CREATE VIEW research AS
SELECT NULL as Fname, NULL as Lname, NULL as Salary, Lname as Manager from EMPLOYEE
WHERE Ssn IN (SELECT Superssn from EMPLOYEE WHERE Dno = (SELECT Dnumber from DEPARTMENT WHERE Dname = 'Research'))
UNION
SELECT Fname, Lname, Salary, Null as Manager FROM EMPLOYEE
WHERE Dno = (SELECT Dnumber from DEPARTMENT WHERE Dname = 'Research');
Can anyone see what is wrong with this? Am I going the right way about it by using the UNION command?
Thank you.
It appears this is what you're trying to accomplish.
select
emp.FName as EmployeeFName
,emp.LName as EmployeeLName
,sup.FName as SupervisorFName
,sup.LName as SupervisorLName
,emp.Salary as Salary
from
Employee emp
inner join Department dept
on emp.dno = dept.dnumber
inner join Employee sup
on emp.SuperSSN = sup.SSN
where
dept.Name = 'Research'
No, you don't want UNION for this.
Why do you have super_ssn on EMPLOYEE and also mgr_ssn on DEPARTMENT? Isn't that redundant?
Anyway, here's another way to do it.
select fname, lname, salary,
(select lname from employee e where e.ssn = employee.superssn) manager
from employee
where dno = (SELECT Dnumber from DEPARTMENT WHERE Dname = 'Research');

How to solve this query in SQL?

I have the following two relations:
EMP(ENO, ENAME, JOB, DATEJOB, SAL, DNO)
DEPT(DNO, DNAME, DIR)
EMP is a relation of the employees with their number ENO, their names ENAME, their job titles JOB, the dates when they get hired, their salary SAL, and the department number they are working on DNO (forgein key which references DNO in DEPT).
DEPT is a relation of the department with the number of each department DNO, the name of the department DNAME, the director of the department DIR (forgein key which references ENO).
My question is:
Write the following query in SQL.
Find the names of the employees that have the same job and the same director as 'Joe'.
My attempt was:
SELECT ENAME
FROM EMP, DEPT
WHERE EMP.DNO = DEPT.DNO
AND (DIR, JOB) IN (
SELECT DIR, JOB
FROM EMP, DEPT
WHERE ENAME = 'Joe'
AND EMP.DEPT = DEPT.DNO
)
AND ENO NOT IN (
SELECT ENO
FROM EMP, DEPT
WHERE ENAME = 'Joe'
AND EMP.DEPT = DEPT.DNO
)
I found the solution of this problem but I couldn't agree of it.
This is what I found:
SELECT ENAME
FROM EMP, DEPT
WHERE ENAME <> 'Joe'
AND EMP.DNO = DEPT.DNO
AND (DIR, JOB) = (
SELECT DIR, JOB
FROM EMP, DEPT
WHERE ENAME = 'Joe'
AND EMP.DEPT = DEPT.DNO
)
The thing is, we have to not consider 'Joe' in the result. But which 'Joe'?
It looks like there's a potential for a "director" to head multiple departments. At least, the information model doesn't seem to be anything to restrict that (i.e. no unique constraint on DIR)
Presumably, we identify employee 'Joe' by finding the tuples(s) in EMP with ENAME attribute equal to 'Joe'.
And presumably, we would identify Joe's "director" by getting the value of the DIR attribute from the DEPT relation.
If we wanted employees in the "same department" as Joe, we could just use the value of the DNO attribute,... but the requirement says "same director". So, just in case the same director heads multiple departments, we'll get all the departments headed by that director.
Then, it's a simple matter of getting all of the employees in those departments, and check for a "job" that matches Joe's "job".
SELECT e.ENAME
FROM EMP j
JOIN DEPT i
ON i.DNO = j.DNO
JOIN DEPT d
ON d.DIR = i.DIR
JOIN EMP e
ON e.DNO = d.DNO
AND e.JOB = j.JOB
WHERE j.ENAME = 'Joe'
Again, if we wanted only the employees in the "same department" as Joe, we could dispense with one of those references to DEPT. The result from this would be different, if Joe's director heads another department, and there's an employee in that other department has the same job... that employee would be excluded from this query:
SELECT e.ENAME
FROM EMP j
JOIN DEPT i
ON i.DNO = j.DNO
-- JOIN DEPT d
-- ON d.DIR = i.DIR
JOIN EMP e
-- ON e.DNO = d.DNO
ON e.DNO = i.DNO
AND e.JOB = j.JOB
WHERE j.ENAME = 'Joe'
If there's a requirement to exclude Joe from the resultset, then we could add another predicate to the WHERE clause. If we don't assume that ENAME can't have a NULL value...
AND ( e.ENAME IS NULL OR e.ENAME <> 'Joe')
You're correct in that the second solution is wrong. If there are two 'Joe's it won't work right. That's why you should exclude based on the unique ENO instead of the non-unique name. The first query won't work for the same reason. In order to be certain, you can't select either just by names or titles or departments, because those can be duplicate. We have three Chris programmers in our department.
Also, that join syntax is obsolete because it can cause confusion to the database in certain circumstances. Please see http://www.w3schools.com/sql/sql_join_inner.asp for an explanation of the current syntax.
The comma style of join you are using has been obsolete for a long time. I think the below is what you're after. The idea is to join a table to its self. This is done by giving the table aliases- source and twin here.
SELECT twin.ENAME
FROM EMP AS source
JOIN EMP AS twin ON twin.DNO = source.DNO AND twin.JOB = source.JOB
WHERE source.ENAME = 'Joe' AND source.ENO <> target.ENO

find the link in tables sql exercise

so I'm stuck on this question where it says:
write a query to retrieve a list of ALL departments in alphabetical order containing the columns DEPARTMENT_ID , DEPARTMENT_NAME , LAST_NAME , FIRST_NAME where last_name and first_name are the name of the Manager of the Department wherever there is one.
I'm have the HR database using the departments, employees table what i have written so far is:
select department_id, department_name, e.last_name, e.first_name
from departments d, employees e
where e.department_id=d.department_id
and d.department_id=e.department_id
and d.manager_id=e.manager_id
having department_name = '%Manager%';
yet i can't figure it out, any tips will help thanks!
A having clause relates to a group by. Where you have no group by, there is no meaning for a having clause.
You just need your join to get the record in the employees table for the manager.
select department_id, department_name, e.last_name, e.first_name
from departments d, employees e
where d.manager_id=e.id
Better is to use the newer join syntax,
select dept.department_id, dept.department_name, emp.last_name, emp.first_name
from departments dept
inner join employees emp on dept.manager_id = emp.id
You don't need conditions for e.department_id=d.department_id and d.department_id=e.department_id, (for one thing these are redundant, so you would only need one if they were needed) because the employees.department_id field refers to the department the employee is in, and what you want is the manager employee record for the department. The manager employee record for the department is represented as the foreign key to the primary key of the employee table.
this might help you...
`select e.first_name,e.last_name,d.department_id ,d.department_name from employees e,departmets d where d.manager_id=e.employee_id order by d.department_name;`