using multiple table in SQL - sql

I've got three tables:
department, employee and telephone
employee has columns EmpNo, Surname, Firstname and DeptNo.
telephone has columns EmpNo and Extension.
department has columns DeptNo and DeptName.
What I am trying to get is the full name, department name and telephone extension.
I think I am almost there but its not working yet.
My query
SELECT e.Firstname, e.Surname, d.DeptName, t.Extension
FROM employee AS e
INNER JOIN department AS d
INNER JOIN telephone AS t
ON e.DeptNo = d.DeptNo
ON t.EmpNo = e.EmpNo;

To fix your problem, move one of the ON clauses before the next JOIN
SELECT e.Firstname, e.Surname, d.DeptName, t.Extension
FROM employee AS e
INNER JOIN department AS d
ON e.DeptNo = d.DeptNo
INNER JOIN telephone AS t
ON t.EmpNo = e.EmpNo;

The ON clause must follow the JOIN that it is modifying.
So:
INNER JOIN department d ON e.DeptNo = d.DeptNo
and
INNER JOIN telephone t ON t.EmpNo = e.EmpNo;

Your query is wrong. Join is not in correct format. Use like below
SELECT e.Firstname, e.Surname, d.DeptName, t.Extension
FROM employee AS e
inner join department AS d
ON e.DeptNo = d.DeptNo
inner join telephone AS t
ON t.EmpNo = e.EmpNo;

Related

find all employees' names who has a manager that lives in the same city as them

I am trying to figure out how to "find all employees' name who has a manager that lives in the same city as them." For this problem, we have two tables. We need to make a query.
"employee"
The employee table that we can refer to has both normal employees and managers
employeeid
name
projectid
city
1
jeff
1
new york
2
larry
1
new york
3
Linda
2
detroit
4
tom
2
LA
"Managertable"
Our manager table which we can refer to with mangerid = employeeid
projectid
mangerid
1
2
2
3
Right now I have found a way to get just the employees and filter out the managers, but now I am trying to figure out the next step to get to the comparison of managers and employees. Would this just be another subquery?
SELECT name
FROM employee e
WHERE employeeid not in(
SELECT mangerid
FROM Managertable pm
INNER JOIN employee e
ON pm.mangerid= e.employeeid);
Expected result :
employee name
jeff
I think the easient way to achieve this would be like this:
SELECT
e.*
FROM employee e
inner join Managertable mt on e.projectid = mt.projectid
inner join employee manager on mt.mangerid = manager.employeeid
WHERE
e.city = manager.city
and e.employeeid <> manager.employeeid;
One approach is a correlated subquery in which we look up the employee's manager's city.
select e.name
from employee e
where city =
(
select m.city
from managertable mt
join employee m on m.employeeid = mt.managerid
where mt.projectid = e.projectid
and m.employeeid <> e.employeeid
);
The same thing can be written with an EXISTS clause, if you like that better.
Based off the table structure you're showing, something like this might work
First find the employee ids of employees who have managers in the same city, then join it back on employee to retrieve all data from the table
;WITH same_city AS (
SELECT DISTINCT e.employeeid
FROM employee AS e
INNER JOIN managertable AS mt ON e.projectid = mt.projectid
INNER JOIN employee AS m ON mt.managerid = e.employeeid
WHERE e.city = m.city
)
SELECT e.*
FROM employee
INNER JOIN same_city AS sc ON e.employeeid = sc.employeeid
I don't see how projectid is relevant in your question because you didn't mention that as a requirement or restriction. Here's a method using a CTE to get the managers and their cities, then join to it to find employees who live in the same city as a manager.
with all_managers as (
select distinct m.managerid, e.city
from manager m
join employee e
on m.managerid = e.employeeid
)
select e.name
from employee e
join all_managers a
on e.city = a.city
and e.employeeid <> a.managerid;
name
jeff
But it you want us to assume that an employee reports to only that manager as listed in the projectid, then here's a modification to ensure that is met:
with all_managers as (
select distinct m.managerid, e.city, e.projectid
from manager m
join employee e
on m.managerid = e.employeeid
)
select e.name
from employee e
join all_managers a
on e.city = a.city
and e.projectid = a.projectid
and e.employeeid <> a.managerid;
View on DB Fiddle
You just need two joins:
one between "managers" and "employees" to gather managers information
one between "managers" and "employees" to gather employees information with respect to the manager's projectid and city.
SELECT employees.name
FROM managers
INNER JOIN employees managers_info
ON managers.mangerid = managers_info.employeeid
INNER JOIN employees
ON managers.projectid = employees.projectid
AND managers_info.employeeid <> employees.employeeid
AND managers_info.city = employees.city

Am I right? I don't know the answer I wrote is right or wrong. (SQL)assignment

For each department headed by a female manager, list the department name, and the number of employees who work for that department.
My Answer:
SELECT E.SEX
FROM EMPLOYEE AS E
WHERE E.Ssn IN (SELECT Essn
FROM DEPENDENT AS D
WHERE E.Sex = D.Sex);
enter image description here
I think your answer is probably wrong. My solution is below:
select aa.name,
count(*) as cnt
(select a.dname
,dnumber
from department as a
inner join employee as b
on a.mgr_ssn = b.ssn
where a.sex = female
) as aa
inner join empoyee as bb
on aa.dnumber = bb.dno
group by aa.name
The logic is following:
1, find all departments which are headed by a female manager. the code is follwing
select a.dname
,dnumber
from department as a
inner join employee as b
on a.mgr_ssn = b.ssn
where a.sex = female
2, group by the department name and count the number of employees who work for that department.
You'll want to study up on it inner joins, aliases/correlation names, and groups/aggregates.
select d.dname, count(*)
from dept d inner join emp em on em.ssn = dept.mgr_ssn
inner join emp e on e.dno = d.dnumber
where em.sex = 'F'
group by d.dname

SQL JOIN : Help using join inisted subquery

I have 2 tables,
The first one is called emp, and has 2 columns called id and name
The second one is called dep, and has columns called id and empid and nameOfDep
if I want to list all emp that have X dep, but don't have Y dep
This is an example I use
Select e.id, e.name
from emp e
where e.id in (Select empid from deptid where deptid=X)
and e.id not in (Select empid from deptid where deptid=Y);
How I can make it using JOIN instead of with subqueries?
An IN can be converted into an INNER JOIN. A Not IN can be converted to LEFT JOIN / NULL Test. Sometimes called an ANTI JOIN.
SELECT e.id,
e.name
FROM emp e
INNER JOIN deptid D_X
ON e.empid = d_x.empid
AND deptid = 'X'
LEFT JOIN deptid D_Y
ON e.empid = d_Y.empid
AND deptid = 'Y'
WHERE d_Y.empid IS NULL
Also I'm making the assumption that when you wrote deptid = X that you meant X to be a literal string and not a field name
SELECT e.id, e.name
FROM emp e
INNER JOIN dep d ON (e.deptID = d.deptID AND d.deptID NOT y)
Add the Department ID to the employee record and then join on that.
EDIT
My bad, updated.
EDIT
Helps to read, go with Conrad's answer.

I need sql query to merge info from 2 tables

i`m new in SQL and i need a tip. I got 2 tables ( employee and department ),
employee table as E:
id (int), name(nvarchar), gender(nvarchar), departmentID(int), dateofbirth(datetime)
department table as D :
dep_id(int), name(nvarchar), location(nvarchar), boss_id(int)
That`s what i need as output table:
E.id / E.name / D.name / D.location / (and last which i cant get with simple join is:) D.boss.name (not simple boss id but real employee name from E table)
Just simple question for advanced people :-)
Join the table a second time for the boss. (This is assuming that boss_id FK's to Employee)
SELECT
E.Id,
E.Name,
D.Name,
D.Location,
B.Name
FROM Employee E
INNER JOIN Department D on E.DepartmentID = D.Dep_id
INNER JOIN Employee B ON D.Boss_id = B.Id
You can write a query using cte as well:
WITH CTE AS(
Select
e.ID,
e.name,
d.boss_id,
d.Location as DepartmentLocation,
d.name as DepartmentName
From Employee e
INNER JOIN Department d on d.boss_id =E.id
)
Select c.id, c.name, e.name as BossName, c.DepartmentLocation, c.DepartmentName
from cte c
Inner Join Employee e1 on e1.id=c.boss_id
SELECT e.Id, e.Name, d.Name, d.Location,
(
SELECT e2.Name
FROM tblEmployee as e2
WHERE e2.id = d.boss_id
) AS [Boss name]
FROM tblEmployee as e
INNER JOIN tblDepartment as d
ON e.DepartmentID = d.dep_ID

"Double Group By" in Oracle SQL?

As I was learning SQL statements I encountered one example (regarding the demo SCOTT database), I have no idea how to solve.
In which department(s) are all salgrades present?
My most promising approach is to group all salgrades and departments in the joined tables emp, dept and salgrade:
SELECT s.grade AS "Salgrade",
d.dname AS "Department ID"
FROM emp e INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
GROUP BY d.dname, s.grade
Executing this gives me the following results:
If I could group this another time by department, COUNT(*) could give me the number of different salgrades per department. Then I could compare this number (with HAVING) to the following subselect:
(SELECT COUNT(*)
FROM salgrade)
Is there any possibility to group a table which already contains
GROUP BY?
Is there another (better) approach I could use?
I am using an apex-oracle-server with "Application Express 4.2.4.00.07"
Minor change from your version, by removing the grouping inside, and this version, first generates, salgrade and department of all employees, and then doing a grouping outside, counting distinct salary grades.
SELECT Department_ID
FROM
(
SELECT s.grade AS Salgrade,
d.dname AS Department_ID
FROM emp e
INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
)
GROUP BY Department_ID
HAVING COUNT(distinct Salgrade) = ( SELECT count(1) FROM salgrade);
I found an even easier solution now:
SELECT d.dname
FROM emp e INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
GROUP BY d.dname
HAVING COUNT(DISTINCT s.grade) = (SELECT COUNT(*) FROM salgrade);
Simple way would be - if performance is not a problem.
SELECT
COUNT(DISTINCT [Salgrade]) AS [COUNT]
,[Department ID]
FROM (SELECT s.grade AS "Salgrade",
d.dname AS "Department ID"
FROM emp e INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
GROUP BY d.dname, s.grade) DEPT_SALE
GROUP BY [Department ID]
There could be better solutions though if we know more of your base tables - emp & salegrade