find the link in tables sql exercise - sql

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;`

Related

practice sql explanation

http://studybyyourself.com/seminar/sql/exercises/8-3/?lang=en
Please provide data about all employees whose salary is higher or equal to the average salary of employees working in the same department (regardless if employees have left the company or not). Required attributes are last name, first name, salary and department name.
SELECT emp.Last_name, emp.First_name, emp.Salary, D.Name
FROM Employee AS emp
INNER JOIN Department AS D ON emp.Department_id = D.ID
WHERE emp.Salary >=
(
SELECT AVG(e.Salary)
FROM Employee AS e
GROUP BY e.Department_id
HAVING e.Department_id = emp.Department_id
)
Can anyone please help explain the solution? Specifically, what does the 'having' clause do in this case that allows the sub-query to work? I get stuck up until that point without the having clause and I expectedly get the 'subquery returns more than 1 row' error but I am not sure how the having clause is fixing the problem.

somebody explain to me how this query works step by step?

I don't yet understand this SQL statement:
select FIRST_NAME
from EMPLOYEES e
where DEP_ID != (select DEP_ID
from EMPLOYEES
where e.MANAGER_ID = EMPLOYEE_ID);
I would write your query as:
select e.FIRST_NAME
from EMPLOYEES e
where e.DEP_ID <> (select e2.DEP_ID
from EMPLOYEES e2
where e.MANAGER_ID = e2.EMPLOYEE_ID
);
This does not functionally change the query but it qualifies all column references and uses <> which is the traditional SQL operator for not equals.
What this query is doing is returning all employees whose department is not the same as their managers department.
How does it do this? The subquery is a correlated subquery. For each row in employees the subquery returns the department id of the manager.
The where clause then checks whether or not it matches the employee's manager.
This subquery will get the Manager's departments.
select DEP_ID from EMPLOYEES where e.MANAGER_ID = EMPLOYEE_ID
So the main query will just get the employees that not managers.
select FIRST_NAME from EMPLOYEES e where DEP_ID != (Managers dept_ID)
It's finding the employees who are not under a particular manager.
Let's see the inner part first:
select DEP_ID from EMPLOYEES where e.MANAGER_ID = EMPLOYEE_ID
This will fetch the department under particular manager
Now the outer part:
select FIRST_NAME from EMPLOYEES e where DEP_ID != <Departments under particular manager>
Now the result will the list of employees's first name not under that manager

Group by clause always produces error "Not a group by expression"

I have two tables
EMPLOYEES(employee_id,first_name,last_name,salary,manager_id,department_id)
and
DEPARTMENTS(department_id,department_name,manager_id)
When I try to create a new table "EMP_DEPT" which contains
department_id ,department_name, dcount(count of employees in each department),
dtotal(total salary of employees in each department),
dmaxsal(maximum salary in a department), dminsal(minimum salary in a department)
it shows ORA00979: not a GROUP BY expression
I did this in oracle
create table emp_dept as(select e.department_id,d.department_name,count(*),sum(salary),max(salary),min(salary)
from employees e,departments d where e.department_id= d.department_id
group by e.department_id);
You seem to be a bit confused in writing your query.
First of all, You are using aliases in columns of table departments, but you're not using aliases in columns of table employees.
select e.department_id,d.department_name,count(*),sum(salary),max(salary),min(salary)
from employees e,departments d
Secondly, you're using a where clause, but shouldn't a left join be a better choice?
where e.department_id= d.department_id
Thirdly, and most importantly, you're doing group by in e.department_id, whereas it should be d.department_id , since there is a parent-child relationship among the tables departments and employees. I don't know how you designed your table, but logically, department_id is supposed to be the primary key in departments table, and foreign key in employees table. That's why, group by e.department_id is incorrect.
Therefore,
group by e.department_id
Should instead be,
group by d.department_id
I think you just need to modify your query in the following way:
create table emp_dept as
(select d.department_id,d.department_name,count(e.*),
sum(e.salary),max(e.salary),min(e.salary)
from departments d
left join employees e
on e.department_id= d.department_id
group by d.department_id);
And hopefully it will fix your problem.

Get employees who worked in more than one department with SQL query

I'm trying to figure out a query which shows the names of the employees who worked in more than 2 departments along with their wage and contact details. I have two tables employees and department. Both of these having the EmployeeName field. I know we have to use the Count function but don't really know how to create the query.
here the tablename and Fields:
Employee (employeeName, wage, contactNo)
Department (employeeName, departmentNo, hours, startDate)
You SQL query would be the following
SELECT e.employeeName, count(departmentNo) FROM Employee e
INNER JOIN Department d ON e.employeeName=d.employeeName
GROUP BY e.employeeName
HAVING COUNT(departmentNo)>2
you can use following query:
SELECT e.employeeName, count(d.departmentname)
FROM Employee e, Department d
where e.deptid=d.deptid
GROUP BY e.employeeName
HAVING COUNT(e.deptid)>=2

Aggregate function couting times hired

I'm using the HR table schema where i have an exercise stating:
The job_history can contain more than one entries for an employee who was hired more than once. Create a query to retrieve a list of employees that were hired more than once. Include the columns EMPLOYEE_ID, LAST_NAME, FIRST_NAME and the aggregate "Times Hired".
What have I done so far is:
select e.employee_id, e.last_name, e.first_name,
count (start_date) as Times_Hired
from job_history jH, employees e
WHERE e.employee_id=jH.employee_id
group by e.employee_id, e.last_name, e.first_name;
Now, my questions are:
should the whole thing be a subquery?
which columns connect the tables job_history and employees?
Because when I run this it displays a few employees only.
You can (and should) rewrite the query with explicit ANSI JOIN syntax to make it clear:
SELECT employee_id, e.last_name, e.first_name,
count (*) AS Times_Hired
FROM employees e
JOIN job_history j USING (employee_id)
GROUP BY employee_id, e.last_name, e.first_name
HAVING count (*) > 1;
I also use a LEFT [OUTER] JOIN to include employees in the result that do not have any rows on job_history (yet).
This is not relevant, since you are only interested in employees ..
than were hired more than once
I implemented this condition with HAVING count (*) > 1.
As to your 2nd question: obviously, employee_id is the column that ..
connects the tables job_history and employees?
Since the column name we join on (employee_id) is identical in both tables I simplified to an equi-join with USING.
And I use count(*) instead of count (start_date), since it has not been declared whether start_date can be NULL, in which case it wouldn't add to the count.
As to your first question: no, you don't need a subquery here.
Alternative JOIN syntax with ON
SELECT e.employee_id, e.last_name, e.first_name,
count (*) AS Times_Hired
FROM employees e
JOIN job_history j ON j.employee_id = e.employee_id
GROUP BY e.employee_id, e.last_name, e.first_name
HAVING count (*) > 1;
Tested both in SQLfiddle.