The question is to find the employee last names for employees who do not have a child of the same sex as themselves.
My code is :
SELECT E.Lname
FROM EMPLOYEE E, DEPENDENT D
WHERE E.Ssn = D.Essn
AND E.Sex <> D.Sex
But I've learned that it is a bad practice to use <>. When I used <> I get multiple names as output.
Smith
Smith
Wong
Wong
Wallace
Is there an alternate way of doing this using NOT IN clause?
Try this
SELECT E.Lname
FROM EMPLOYEE E, DEPENDENT D
WHERE E.Ssn = D.Essn
AND D.Relationship IN ("Son", "Daughter")
AND E.Sex = D.Sex
GROUP BY E.Ssn
Instead of using a Cartesian product from the query, join use left join to not repeat entries.
i.e.
SELECT E.Lname
FROM EMPLOYEE E LEFT JOIN DEPENDENT D
ON E.Ssn = D.Essn
WHERE E.Sex <> D.Sex
NOTE Query would give duplicate last name as long as multiple employee has same last name.if unique last name is required then try below query
SELECT DISTINCT(E.Lname)
FROM EMPLOYEE E LEFT JOIN DEPENDENT D
ON E.Ssn = D.Essn
WHERE E.Sex <> D.Sex
You can use NOT EXISTS:
SELECT E.Lname
FROM EMPLOYEE E
WHERE NOT EXISTS (SELECT 1
FROM DEPENDENT D
WHERE E.Ssn = D.Essn
AND E.Sex = D.Sex
AND D.Relationship IN ('Son','Daughter')
)
This will only return records from the EMPLOYEE table, so no multiple records returned.
Edit: Noticed the relationship options included 'spouse'.
Try this :
SELECT DISTINCT(EMPLOYEE.Lname) FROM DEPENDENT LEFT JOIN EMPLOYEE ON DEPENDENT.Essn=EMPLOYEE.Ssn WHERE (DEPENDENT.Sex <> EMPLOYEE.Sex) AND DEPENDENT.Relationship IN ('Daughter','Son');
Find the a list of employees who have a child with the same sex as them and then exclude them from the list of all those who have a child.
SELECT DISTINCT A.Lname
FROM Employee A
INNER JOIN Dependent B
on A.Ssn = B.essn
Where B.Relationship in ('Son', 'Daughter')
AND A.Ssn not in (
SELECT AA.ssn
FROM Employee AA
INNER JOIN Dependent BB
on AA.Ssn = BB.essn
Where BB.Relationship in ('Son', 'Daughter')
And AA.Sex = BB.Sex
)
Related
I have the following 3 tables for students and I need to find the names of students who currently are enrolled in classes that meet at the same time
student(**snum**, sname, major, level, age)
class(**cname**, meets_at, room)
enroll(**snum**, **cname**)
The keys for each table is in bold.
I have tried the folling code and I'm not sure whether I'm close to the correct answer here.
select s.sname
from student s
join
( select c.cname
, c.meets_at
, (count(*)
from class c
having count( * ) > 1
) e
on c.cname = e.cname
and s.snum = e.snum;
I would think of this as joining on students with meetsat. So, this gets students with their class times:
select s.sname, c.meets_at
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname;
Then, to get the duplicates, use aggregation and filter using having:
select s.snum, s.sname, c.meets_at, count(*) as cnt
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
Note that this includes the ids as well as the name, because two students could have the same name.
Finally, a student could have multiple pairs of classes that conflict, but you only want to see the student once. Although the above is probably sufficient for your purposes, a more accurate solution for the stated problem would be:
select distinct s.sname
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
select s.snum, s.sname, c.meets_at ,count(*) as cnt into #tempStudents
from students s
join enrolls e on s.snum = e.snum
join classes c on c.cname = e.cname;
Put the whole data in temporary table
select sname from #tempStudents
group by snum,sname ,meets_at
having cnt >=2
Now apply filtration on temporary table for getting desire data
and if u need distinct name of student put Distinct keyword before sname.
I need to make sql question which will show all departments with at least 2 people in it.
SELECT department.name
FROM department
INNER JOIN employee
ON department.id = employee.department_id
GROUP BY employee.id
HAVING COUNT(employee.id) >= 2;
It's not showing me anything with this query
I think you using GROUP BY on wrong column.
If you want to count employee in each department, then you need to GROUP BY department.id.
SELECT department.id, department.name, COUNT(employee.id) AS total_employee
FROM department
INNER JOIN employee
ON department.id = employee.department_id
GROUP BY department.id, department.name
HAVING COUNT(employee.id) >= 2;
Try this:
SELECT d.name
FROM department d
WHERE
(SELECT COUNT(*) FROM employee e
WHERE d.id = e.department_id) >= 2
In this way if you want to change your limit (instead of 2, another value) your query will work.
If you use INNER JOIN if you want, in the future all departments with no employees you can't use it.
There is a table Employee as below:
I need finds out employees who earn more than their managers and I figure out two methods:
SELECT a.Name AS Employee FROM Employee a, Employee b WHERE a.Salary > b.Salary AND a.ManagerId = b.Id;
SELECT a.Name AS Employee FROM Employee a INNER JOIN Employee b ON a.Salary > b.Salary AND a.ManagerId = b.Id;
Both of them work well and have close speed.
What's the difference between them? Thanks.
Those queries are equivalent. But you should use the join syntax instead of commas in the from clause. INNER JOIN ON vs WHERE clause
Here's an alternative option which might have a better performance using exists:
select e.Name AS Employee
from employee e
where exists (
select 1
from employee e2
where e.managerid = e2.id and e.salary > e2.salary
)
I have two tables, for example the Employee and Project tables:
Employee (id, dept, joining_date)
Project (emp_id, project)
With Project having foreign key from Employee table.
I have to query on project and dept and return Employee in the order of their joining_date. Which query will work faster on big data set on the queries below?
select * from Employee where id in (select p.emp_id from Project p join Employee e on p.emp_id = e.id where p.project = 'project1' and e.dept = 'dept1') order by joining_date
select * from Employee where id in (select p.emp_id from Project p join Employee e on p.emp_id = e.id where p.project = 'project1' and e.dept = 'dept1') and dept = 'dept1' order by joining_date
Or is there any better and simpler way to do so?
The outer query using the IN() expression serves no purpose is entirely unnecessary. This will produce the output you need:
select e.*
from Project p
inner join Employee e on p.emp_id = e.id
where p.project = 'project1' and e.dept = 'dept1'
order by joining_date
SELECT
e.lname AS employee_name
, s.lname AS supervisor_name
, e.superssn AS supervisor_ssn
FROM employee e INNER JOIN employee s
WHERE e.superssn=s.ssn
I actually have two questions. The first one is, the above statement works just fine. However right now it will show bunch of employees with their supervisor. Not well organized. By the way there are three supervisors. Is there a way to show let's say supervisor A with employees A and supervisor B with employees B and so on?
The second problem is that I also tried to just count the number of employees for each supervisor rather than showing their name with COUNT(), I tried several different ones but non worked.
A few things
1) It is good practice to keep your join predicate with your join. So change:
FROM employee e INNER JOIN employee s WHERE e.superssn = s.ssn
To:
FROM employee e INNER JOIN employee s ON e.superssn = s.ssn
2) To keep them together by supervisor, just use an order by:
SELECT
e.lname AS employee_name
, s.lname AS supervisor_name
, e.superssn AS supervisor_ssn
FROM employee e INNER JOIN employee s ON e.superssn = s.ssn
ORDER BY s.lname
3) To do a count of employees for each supervisor use a group by and the COUNT aggregate function
SELECT
s.lname AS supervisor_name,
COUNT(*) AS employee_count
FROM employee e INNER JOIN employee s ON e.superssn = s.ssn
GROUP BY s.lname
ORDER BY s.lname