Querying SQL table a second time with info from the first - sql

I am running a query against a PeopleSoft database, and am unsure whether it is possible to get information from the same table, based on the initial query, in a single call. For example, the table I am hitting returns EmployeeID, FullName, FirstName, LastName, Position_NBR, and ReportsTo. But the ReportsTo is in the form of the manager's Position_NBR (found in same table), and I would like to get it in the name format. I would like to do something like this, but not sure if it is possible:
SELECT Employee_ID, FullName, FirstName, LastName, Position_NBR
,(Select Name From Employee Where Position_NBR='12345') As Manager
From Employee
Where EmployeeID='8675309'
Is this even possible, or do I need to fully return the first piece before I can use the second?

Yes, you can refer to the first table and it's best to limit the result of the subquery to 1 result (just in case the employee has 2 o more managers)
SELECT Employee_ID, FullName, FirstName, LastName, Position_NBR
,(Select Top 1 E2.Name From Employee as E2 Where E2.Position_NBR=Employee.Position_NBR) As Manager
From Employee
Where EmployeeID='8675309'
(T-SQL Syntax)

You should be able to do this by linking fields.
Here are some examples using the Oracle Database:
e.g.
SELECT
table1.Employee_ID, table1.Name, table1.Boss_ID
,(select table2.name from Employee table2 where table1.Boss_ID = table2.Employee_ID) As Manager
From
Employee table1
Where
table1.Employee_ID='333'
/
Alternately, try a SQL JOIN.
SELECT
table1.Employee_ID, table1.Name, table1.Boss_ID
,table2.Name As Manager
From
Employee table1
inner join Employee table2
on table1.Boss_ID = table2.Employee_ID
Where
table1.Employee_ID='333'
/
Here is a link to a working example with some fake data:
http://sqlfiddle.com/#!4/210580/7

Related

How to alias column in SQL plus

When I write this query in sql plus show me error (ORA-00998: must name this expression with a column alias)
create or replace view vw_salary as select dname ,
(select count(*) from employee where dno=department.dnumber) from department;
Columns in a view need to have a name. So, you need as after the subquery:
create or replace view vw_salary as
select dname,
(select count(*) from employee e where e.dno = d.dnumber
) as NumEmployees
from department d;
I strongly encourage you to use table aliases and qualified column names (that is use the table alias). This is particularly important for correlated subqueries, where it is easy to make a mistake and that is hard to debug.
I also note that the view is called vw_salary, but there is no salary information.
select department.dname, count(employee.dno) as empCount
from department
left join employee
on employee.dno = department.dnumber
group by department.dname
I think this will be more efficient than your current format
It means you need to name the count expression ... try the following, you can change "TheCount" to any name you want to use.
create or replace view vw_salary as select dname ,
(select count(*) AS TheCount from employee where dno=department.dnumber) from department;

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.

Replacing a table value with the previous expression in oracle

Ok so I am having the following scenario
I have a table called employees and have to replaced the last names for some of the people there under the following conditions:
1-The last name must be replaced only to those employees who work on Oxford.
2-Their new last name is going to be the last name of the person that has their employee number -1 ( for instance employee#173 should have now employee#172 last name instead)
This is how I started the query:
select last_name,num_emp
from employees
where num_emp in(
select e.num_emp
from employees
join departments using(num_dept)
join office using(id_office)
where city='Oxford')
And I did a second query to make sure which values were going to replace which
Select last_name,num_emp
from employees
where num_emp in(
select (e.num_emp-1)
from employees
join departments using(num_dept)
join office using(id_office)
where city='Oxford')
Now I thought I could do this and make the code work... but it didn't:
update employees
set last_name=(select last_name
from employees
where num_emp in(
select (e.num_emp-1)
from employees
join departments using(num_dept)
join office using(id_office)
where city='Oxford')
Got error saying unexpected end of SQL command...
So I thought on making a change because I believed having too many values on the set was not the point and here is how I did it for last time:
update employees
set last_name=(select last_name
from employees)
where num_emp =(
select (e.num_emp-1)
from employees
join departments using(num_dept)
join office using(id_office)
where city='Oxford')
Got an error that says is missing right parenthesis, which I know it does not express whaat the issue is. I know I am missing something and part of the sintaxis is wrong as well as I may need to créate another table and add those values so that they get saved there and I can compare them with the original ones, but at this point I am totally blocked and can't discover what is the mistake I am doing. Please help me I'd really apprecciate it!
You are getting confused with what to update and what to update with in your statements.
Here is what to update. I use IN clauses to make it plain. An EXISTS clause would also be appropriate.
update employees
set last_name = ...
where num_dept in
(
select num_dept
from departments
where id_office in
(
select id_office
from office
where city = 'Oxford'
)
);
And here is what to update with:
set last_name =
(
select last_name
from employees prev_employee
where prev_employee.num_emp = employee.num_emp - 1
)
You should use the analytical lag function, then you also fill in gaps if for example employee 172 doesn't exist and you have to put the name of employee 171 in 173.
Your select should be something like this
with new_emp as
(select last_name,lag(last_name, 1, 0) over (order by num_emp) as new_last_name, num_emp
from employees)
select *
from new_emp
where num_emp in(
select e.num_emp
from employees e
join departments using(num_dept)
join office using(id_office)
where city='Oxford');
This select will give you the original last name, new last name, employee number.
Then afterwards your update should be this:
update employees x
set last_name = (with new_emp as
(select last_name,lag(last_name, 1, 0) over (order by num_emp) as new_last_name, num_emp
from employees)
select new_last_name
from new_emp ne
where ne.num_emp = x.num_emp)
where x.num_emp in(
select e.num_emp
from employees e
join departments using(num_dept)
join office using(id_office)
where city='Oxford');

Creating table using select statement from multiple tables

I have this university task to create table using SELECT statement from multiple tables, but it's not as simple... here's basic info:
I'm using 2 tables -
CITY(city_ID, name);
PERSON(person_ID, name, surname, city_ID);
--city_ID is FK indicating in which city person was born.
Now my task is to create new table
STATISTICS(city_ID, city_name, number_of_births);
--number_of_births is basically a count of people born in each city
Problem is that I have to use only SELECT statement to do so.
I've tried something like this: (I'm well aware that this cannot possibly work but as to give you a better idea where I'm stuck)
CREATE TABLE Statistics AS
(SELECT city.city_ID, city.name as "city_name", number_of_births AS
(SELECT COUNT(*) FROM person WHERE person.city_id = city.city_id)
FROM city, person);
For SQL Server you can do SELECT * INTO. Something like this:
SELECT
*
INTO Statistics
FROM (
SELECT
city.city_ID,
city.name as "city_name",
(SELECT COUNT(*) FROM person WHERE person.city_id = city.city_id) as 'number_of_births'
FROM city
inner join person on city.city_id = person.city_id
) t1
(Posted on behalf of the question author).
Ok, this got really messy. Dave Zych's answer was correct when rewritten in Oracle dialect.
CREATE TABLE Statistics AS SELECT * FROM (
SELECT DISTINCT
city.city_ID,
city.name AS "City_name",
(SELECT COUNT(*) FROM person WHERE person.city_ID = city.city_ID) AS "number_of_births"
FROM city INNER JOIN person ON city.city_ID = person.city_ID);

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