Retrieving the Name from the same row using a recently acquired ID - sql

I was messing around and wanted to know (title). Let me explain.
Let's say I have an Employee table and in that table is ID ManagerID and Name ID. So after making the Query to find everyone's manager you are left with something like this as a result
Person's Name | Their ID | Manager ID
Now he's what I want to know if it is possible. The managers are also in this employee table and they either have other employees as their manager or they dont have a manager. So technically I have all the information I need at my disposal. Just need to exchange the int (ManagerID) with the Person's name that is in the same row.
Is that possible or is SQL not able to handle that kind of swapping.
Edit:
So here's the test table and values I've been using:
Create table Employee
( ID int,
Name varchar (50),
ManagerID int );
Insert into Employee
Values( 101, 'Joe Smoeington', 102);
Insert into Employee
Values( 102, 'This Guy', 106);
Insert into Employee
Values(103, 'Test', 102);
Insert into Employee
Values(104, 'Rob', 105);
Insert into Employee
Values(105 , 'Jeremy', NULL);
Insert into Employee
Values(106 , 'Sam', NULL);
My stuck point:
Select ID, Name, ManagerID
From Employee
Where ManagerID IS NOT NULL
Ultimately this will get you a table that looks like this:
ID Name ManagerID
101 Joe Smoeington 102
102 This Guy 106
103 Test 102
104 Rob 105
Things Ive tried:
Select ID, Name, ManagerID
From Employee Join Employee
On Employee.ID = Employee.ManagerID
Where ManagerID IS NOT NULL
Select ID, Name, (Select Name From Employee Where (didnt know what to put here and gave up on this attempt)
From Employee
Where ManagerID IS NOT NULL
There are others just not worth mentioning

You can use self join something like this.
SELECT T1.Name AS Employee_Name,T1.ID AS Employee_ID,(IFNULL(T2.ID,'NA')) AS ManagerID
FROM
employee T1
LEFT JOIN employee T2 ON T1.ManagerID = T2.ID
EDIT :
IF you want to see only those employee who has manager.
SELECT T1.Name AS Employee_Name,T1.ID AS Employee_ID,(IFNULL(T2.ID,'NA')) AS ManagerID
FROM
employee T1
INNER JOIN employee T2 ON T1.ManagerID = T2.ID
Here is the DEMO
hope This Helps.

Related

Recursion in Snowflake

Long time listener, first time caller.
Im trying to learn recursion in Snowflake SQL with a classic Organizational Chart. The output Im trying for would be the total salary for each manager of employees, including both direct and indirect employees of that manager.
create table Employee(
employeeid int primary key,
managerid int,
title string
);
INSERT INTO EMPLOYEE VALUES(1,NULL,'CEO');
INSERT INTO EMPLOYEE VALUES(2,1,'SVP 1');
INSERT INTO EMPLOYEE VALUES(3,1,'SVP 2');
INSERT INTO EMPLOYEE VALUES(4,2,'DIR 1');
INSERT INTO EMPLOYEE VALUES(5,2,'DIR 2');
INSERT INTO EMPLOYEE VALUES(6,2,'DIR 3');
INSERT INTO EMPLOYEE VALUES(7,3,'MGR 1');
INSERT INTO EMPLOYEE VALUES(8,3,'MGR 2');
INSERT INTO EMPLOYEE VALUES(9,3,'MGR 3');
INSERT INTO EMPLOYEE VALUES(10,9,'ASST');
create TABLE EMPLOYEE_SALARY(
EMPLOYEE_ID INT PRIMARY KEY,
SALARY INT
);
INSERT INTO EMPLOYEE_SALARY VALUES(1,100);
INSERT INTO EMPLOYEE_SALARY VALUES(2,90);
INSERT INTO EMPLOYEE_SALARY VALUES(3,90);
INSERT INTO EMPLOYEE_SALARY VALUES(4,80);
INSERT INTO EMPLOYEE_SALARY VALUES(5,80);
INSERT INTO EMPLOYEE_SALARY VALUES(6,80);
INSERT INTO EMPLOYEE_SALARY VALUES(7,70);
INSERT INTO EMPLOYEE_SALARY VALUES(8,70);
INSERT INTO EMPLOYEE_SALARY VALUES(9,90);
INSERT INTO EMPLOYEE_SALARY VALUES(10,60);
select
managerid,
sum(salary) as salary
from
(
select emp.managerid,
emp.employeeid,
sal.salary
from employee emp
inner join employee_salary sal on emp.employeeid = sal.employee_id
)
group by 1
start with managerid is Null
connect by managerid = prior employeeid
The error Im getting is "SQL compilation error: error line 3 at position 12 invalid identifier 'SALARY'".
Thanks in advance for any direction you can offer.
I would approach this with a recursive common table expression. Snowflake supports that standard syntax, and I find it easier to follow that the connect by clause:
with cte as (
select managerid, employeeid from employee
union all
select c.managerid, e.employeeid
from cte c
inner join employee e on e.managerid = c.employeeid
)
select c.managerid, sum(s.salary) total_salaries
from cte c
inner join employee_salary s on s.employeeid = c.employeeid
group by c.managerid
I'd recommend the CTE approach from GMB however if you want your SQL to work here's one approach :
select
managerid,
sum(salary) salary_summed
from
(
select
*
from
(
select
emp.managerid,
emp.employeeid,
sal.salary
from
employee emp
inner join employee_salary sal on emp.employeeid = sal.employee_id
) start with managerid is Null connect by managerid = prior employeeid
)
group by managerid

SQL help to make a particular select statement for a table

CREATE TABLE person (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
);
INSERT INTO person VALUES (0, 'Pat', 'Johnson', 25);
INSERT INTO person VALUES (1, 'John', 'Wells', 28);
So I have a table called person and I am trying to query all people younger than Pat Johnson, but I do not want to query it by hard coding.
SELECT first_name, last_name FROM person WHERE age < 25;
^^^ this is an example of what I do not want to do.
You can try using a subquery
SELECT first_name, last_name FROM person
WHERE age<(select age from person where first_name='Pat' and last_name='Johnson')
We can try an anti-join approach:
SELECT t1.first_name, t1.last_name
FROM yourTable t1
LEFT JOIN yourTable t2
ON t1.age > t2.age AND
t2.first_name = 'Pat' AND
t2.last_name = 'Johnson'
WHERE
t2.first_name IS NULL;

SQL query - Dept and Employee table, some departments may not have managers

There are two tables:
Employee
---------
emp_id
emp_name
emp_contact
salary
mgr_emp_Id
Dept_No
Dept
-----
Dept_No
Dept_name
Dept_Location
Write a SQL statement to list all department names along with location and also manager name if a manager has been assigned to the department. Note that some departments still do not have a manager.
Is the following correct?
SELECT Dept_name, Dept_Location, emp_name AS Mgr_name
FROM Dept
LEFT JOIN Employee ON (Dept.Dept_No = Employee.Dept_No AND mgr_emp_id = emp_id)
Can this be achieved without join too? If yes, how?
Yes, you can achieve that without a JOIN, even though I prefer using JOINs. Your query will have to be modified. Here's how...
Example
http://sqlfiddle.com/#!2/596b45/4 (MySQL 5.5)
http://sqlfiddle.com/#!3/bbad4/1 (SQL Server 2008)
http://sqlfiddle.com/#!12/bbad4/1 (PostgreSQL 9.2)
Assumption
1) In the employee table: manager id + department id will be unique
2) In the employee table: if employee Clark is ID 5 and has a manager with ID 1, there will a record in the table with ID 1
3) MySQL 5.5 is being used
Structure
create table dept
(
dept_no int not null,
dept_name varchar(100) not null,
dept_location varchar(100) not null,
primary key (dept_no)
);
create table employee
(
emp_id int not null,
emp_name varchar(100) not null,
mgr_emp_id int,
dept_no int not null,
primary key (emp_id),
key employee_mgr_emp_id (mgr_emp_id),
foreign key fk_employee_dept_dept_no (dept_no) references dept (dept_no) on delete no action on update no action
);
insert into dept values
(1, 'Dept-1', 'Chicago'),
(2, 'Dept-2', 'London');
insert into employee values
(1, 'Clark Mgr', null, 1),
(2, 'Cameron Emp', 1, 1),
(3, 'Charlie Emp', 1, 1),
(4, 'Layton Emp', null, 2),
(5, 'Linda Emp', null, 2);
MySQL 5.5 query
Without JOIN
select
list.*,
emp_id,
emp_name
from employee,
(
select
distinct
dept.dept_no,
dept.dept_name,
dept.dept_location,
employee.mgr_emp_id
from dept, employee
where
dept.dept_no = employee.dept_no
and employee.mgr_emp_id is not null
) list
where
employee.emp_id = list.mgr_emp_id;
With JOIN (although not completely identical to the above. I prefer using JOINs)
select
list.*,
emp_id,
emp_name
from employee
inner join
(
select
distinct
dept.dept_no,
dept.dept_name,
dept.dept_location,
employee.mgr_emp_id
from dept
left join employee on dept.dept_no = employee.dept_no
where
employee.mgr_emp_id is not null
) list
on employee.emp_id = list.mgr_emp_id;
How does it work
First we want to get a list of all departments that have a manager ID of not null in the employee table. To do that, we use this query below. This query will give 2 records for Chicago because there are 2 records in employee table with a valid manager ID for Chicago's department.
Without JOIN
select
dept.dept_no,
dept.dept_name,
dept.dept_location,
employee.mgr_emp_id
from dept, employee
where
dept.dept_no = employee.dept_no
and employee.mgr_emp_id is not null;
With JOIN
select
dept.dept_no,
dept.dept_name,
dept.dept_location,
employee.mgr_emp_id
from dept
left join employee on dept.dept_no = employee.dept_no
where
employee.mgr_emp_id is not null;
To get only one record, we will use distinct keyword:
select
distinct
dept.dept_no,
...
Great, so now we know who the manager is for each department no. Let's find this person's name. To do that, we put our query in a subquery (which I nicknamed/aliased as list) and then combine it with employee table to get the desired result.

does anyone know how to list the empid and the name of all supervisors if supervisors are in employee table too?

I have a table that contains empid, name, salary, hiredate, position and supervisor (which includes empid, not the name). How do I list the empid and name of all supervisors?
The output has to have to columns supervisor (and a list of their empid) and their names. This is the create statement used to create the Employee table:
/* Create table Employee */
IF OBJECT_ID('Employee', 'U') IS NOT NULL
DROP TABLE Employee
GO
CREATE TABLE Employee (
emp_id NCHAR(5),
name NVARCHAR(20),
position NVARCHAR(20),
hire_date DATETIME,
salary MONEY,
bcode NCHAR(3),
supervisor NCHAR(5)
)
I have tried a variety of statements using having statement and count but they don't seem to work.
select emp_id, name from employee where position='manager';
I tried this but it doesn't work. Anyone smart that knows how to do it?
You will have to join the table back on itself:
select a.name, a.position, a.hiredate, a.salary, a.supervisorid,
isnull(b.name, '') as SupervisorName
from EmployeeTable a
left join EmployeeTable b
on a.SupservisorID=b.ID
The left join will make sure that the employees who do not have supervisors are returned, and isnull(b.name, '<NONE>') can be used if you would like to have something other than NULL as a value in those cases.
SELECT e.empid ,ISNULL(b.name, 'No supervisor') SupervisorName
FROM employee e LEFT JOIN employee b
ON e.supervisorid = b.empid
Inner join will leave out the people who do not have a supervisor , Use left join to get all the employees
If you want supervisors only, you just need to select rows whose emp_id values are found in the supervisor column:
SELECT
SupervisorID = emp_id,
SupervisorName = name
FROM dbo.Employee
WHERE emp_id IN (SELECT supervisor FROM dbo.Employee)
;

same table, 1 field to 2 field query

I have 2 tables: 1st holds employees (of ones in any position) and the 2nd holds manager employee relations with id numbers.
I want to write a query like
1st field: name(employee),
2nd field: name(manager)
How can I do that?
No nested queries required, just use standard joins:
select e.*, m.*
from
employee e
left join employee_managers em
on e.id = em.emp_id
left join employee m
on m.id = em.man_id
Each row will contain all fields of employee (possibly several rows for one employee if it has several associated managers) and all fields of his corresponding manager (or NULLs if employee has no manager).
You can do that with one table:
Employee
--------
EmployeeId int
Name varchar(50)
ManagerId int
ManagerId points to the manager's entry in the same table. The CEO will have a ManagerId of null. An example table definition:
create table Employees (
EmployeeId int auto_increment primary key
, Name varchar(50)
, ManagerId int
, foreign key (ManagerId) references Employees(EmployeeId)
);
With some example data:
insert into Employees (Name) select 'The Chief';
insert into Employees (Name, ManagerId) select 'Grunt 1',
(select EmployeeId from Employees where Name = 'The Chief');
insert into Employees (Name, ManagerId) select 'Grunt 2',
(select EmployeeId from Employees where Name = 'The Chief');
insert into Employees (Name, ManagerId) select 'Secretary',
(select EmployeeId from Employees where Name = 'The Chief');
To find the name of the second Grunt's manager, you could query like:
select mgr.Name
from Employees mgr
inner join Employees grunt
on grunt.managerid = mgr.employeeid
where grunt.name = 'Grunt 2';