what is wrong with my nested subquery and substr function - sql

I'm learning sql and I have this question that I can't solve by myself :
Select name, job, city for employees who do not work in
the same service as their direct supervisor.
I have two tables :
EMP (NOEMP, NAME, FIRST, NAME, EMPLOI, SUP, HIRING, SAL, COMM, NOSERV)
SERV (NOSERV SERVICE CITY)
After an analysis of the two tables I can know if a employee is not working in the same city as his supervisor by extracting the second figure of the SUP column.
And here you can read my proposition to solve the question.
select e1.nom, e1.prenom, e1.emploi, s1.ville, substr(sup,2,1), e1.noserv`
from emp e1 join
serv s1
on e1.noserv = s1.noserv
where e1.nom in (select distinct e3.nom
from emp e3 join
emp e4
on e3.noserv = e4.noserv
where substr(e3.sup,2,1) != e4.noserv
);
Everything is working well but I have an unexpected output as you can see here in this screen from my laptop.
output of the query
Here the sample of the data :
serv table
emp table

This answer makes the following assumptions:
sup is the empno of the supervisor
noserv represents the "service"
The second assumption means that you don't need the serv table. It is sufficient to use a join and an inequality on noserv:
select e.*
from emp e join
emp m
on m.sup = e.empno and m.noserv <> e.noserv;

Related

How to use subqueries in oracle

Hello I'm trying to solve this question with a subquery:
Select names, service number, jobs and salaries of
people working in the same city as HAVET. (havet is a name)
And I have only two table the first one is the emp table with the column (noserv, name, job, salaries) and the second one is the SERV table with the column (noserv, nameserv, city)
I know that I have to use a subquery but I don't know how to do it.
Semi-pseudocode (CTE won't work, obviously).
with emp (noserv, name, job, salaries),
serv (noserv, nameserv, city)
-- This is what you're looking for, I presume
select e.*
from emp e join serv s on e.noserv = s.noserv
where s.city = -- subquery returns city where HAVET lives
(select s1.city
from serv s1 join emp e1 on e1.noserv = s1.noserv
where e1.name = 'HAVET'
);
Try this:
-- This is a normal query with a left join
select *
from emp e
left join s on e.noserv = s.noserv
where s.city =
-- get Havet's city from the subquery.
(select s.city
from emp e
left join s on e.noserv = s.noserv
where e.name = 'HAVET')
Try this one, change the column name according to your table and column names.
Select e.name,e.serviceNubmer,e.Job,e.salaries
from emp e,serv s
where
e.noserv = s.noserv
and s.city ='HAVET';

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

How to get result in following scenario

I have table
EMP(id int primary key, name varchar2(15), mgrID int).
Now this table contain all employees(including worker and manager) in company. mgrID column contain id of employee to whom they are reporting.
I want to list the name of worker who is not manager along with their name of manager.
What to do for such query.
I tried nested select query as follows:
select name, (select name from EMP where mgerID is NULL)
as Manager from EMP;
Will this query give proper result?
You could use a self-join:
SELECT e.name AS name, m.name AS manager_name
FROM emp e
JOIN emp m ON e.mgrid = m.id
Your query should fail because you sub-query is uncorrelated and will return multiple results if you have multiple top-level managers.
select name
, (select name from EMP b where b.ID = a.mgerID ) as Manager
from EMP a;
I think the self-join is the more canonical solution, but you should understand the correlated subquery as well as it has many application.

SQL query how to print out manager name?

I need to create a query to display employee name and number along with their super's name and super number. Listing should also include employees who don't have any supervisor.
Select e.ename,e.empno,super.ename,super from emp e;
I don't know how to print out the manager/supervisor name, i just need that.
Join the table to itself using an outer join:
select e.ename, e.empno, super.ename, super.empno
from emp e
left join emp super on super.empno = e.super_empno
The left join will still return rows from emp that do not have a super defined.
EDIT
Due to OP's comment, here's how to do it without a join (using a nasty correlated sub-query):
select
ename,
empno,
(select super.ename from emp where empno = e.super_empno) as super_name,
super_empno
from emp e;

Deriving a column's data from a matching column in SQL

So I have a table that has, employee number, employee name, supervisor number.
I want to run a query that will retrieve employee name, employee number, supervisor name and supervisor number. Only one employee doesn't have a supervisor meaning it will have to display nulls. How would I do this? I'm using Oracle SQL Plus. My attempts haven't worked at all! Any help would be much appreciated.
SELECT ename Employee, empno Emp#, super Manager#
FROM emp;
That gets me three of the columns but to be honest I don't even know where to start to get the supervisors names.
It's for university, but I'm studying for a test it's not for an assignment so no cheating happening here :).
The following should work, and give you nulls if the employee has no supervisor:
SELECT empGrunt.ename Employee
, empGrunt.empno EmpNum
, empSuper.ename SupervisorName
, empSuper.empno SupervisorName
FROM emp empGrunt LEFT OUTER JOIN emp empSuper
ON empGrunt.super = empSuper.empno
Assuming that SupervisorNumber is a foreign key relationship back to the Employee table (where it's the EmployeeNumber of the supervisor's record), then you need to use an outer join.
What you need in this case is a left join:
select
e.EmployeeName,
e.EmployeeNumber,
s.EmployeeName as SupervisorName
from Employee e
left join Employee s on s.EmployeeNumber = e.SupervisorNumber