Creating new columns from data in other columns based on primary key - sql

7.1 List the employee name, employee title, manager name, and manager title for each employee.
Use clear column aliases for your results, and do not exclude any employees in your list.
I'm new to SQL so bear with me. I've managed to have the output list of every employee, their job title, and the employee ID of the employee of they report to (aka their manager). I can't for the life of me figure out how to properly add two additional columns (ManagerName and ManagerJobTitle) with the necessary correct information in it.
Here is my query so far.
Select (FirstName + ' ' + LastName) as EmployeeName, Title as JobTitle, ReportsTo
From Employees E
Order By ReportsTo

You didn't show any schema for your tables, but from your query I can see you are missing the join with the manager table, from where those two columns where probably supposed to come.
Edit: OK, now I get it. The employee table relates to itself. You didn't specified the PK for the table, so I'll assume the Employee has an Id. If the key is another column, just change it in the query below:
Select (E FirstName + ' ' + E.LastName) as EmployeeName,
E.Title as JobTitle,
(R.FirstName + ' ' + R.LastName) as 'ManagerName',
R.Title as 'ManagerTitle'
From Employees E
LEFT JOIN
Employees R ON E.ReportsTo = R.Id
Order By ReportsTo
Edit 2: Changed from INNER JOIN to LEFT JOIN, as a employee can have no manager.

Select (E.FirstName + ' ' + E.LastName) as EmployeeName, E.Title as JobTitle, mgr.ReportsTo, (mgr.FirstName + ' ' + mgr.LastName) as ManagerName, mgr.Title as MamagerJobTitle
From Employees E
Left join Employees mgr on E.EmployeeID = mgr.ReportsTo
Order By ReportsTo
Note: As per my understanding, ReportsTo column has employeeID who have report to any manger, if not please replace that column with mgr.ReportsTo

Related

SQL hierarchyid type issue

The full task sounds like this: Display the content of employees whose immediate supervisor is younger and less employed in the company.
Columns:
Manager Name | Date of hiring a manager | Head's date of birth
Employee name | Employee hiring date | Employee's date of birth
I already broke my head here:
SELECT
LastName + ' ' + FirstName AS SupervisorFullName,
HireDate,
BirthDate,
(SELECT LastName + ' ' + FirstName
FROM HumanResources.Employee AS subHrE
WHERE HrE.OrganizationNode.IsDescendantOf(subHrE.OrganizationNode) = 1
AND HrE.OrganizationLevel = HrE.OrganizationNode.GetLevel() + 1) AS EmployeeFullName,
(SELECT HireDate
FROM HumanResources.Employee AS subHrE
WHERE HrE.OrganizationNode.IsDescendantOf(subHrE.OrganizationNode) = 1
AND HrE.OrganizationLevel = HrE.OrganizationNode.GetLevel() + 1) AS HireDateEmp,
(SELECT BirthDate
FROM HumanResources.Employee AS subHrE
WHERE HrE.OrganizationNode.IsDescendantOf(subHrE.OrganizationNode) = 1
AND HrE.OrganizationLevel = HrE.OrganizationNode.GetLevel() + 1) AS BithDateEmp
FROM
HumanResources.Employee as HrE
JOIN
Person.Person as P ON HrE.BusinessEntityID = P.BusinessEntityID
ORDER BY
SupervisorFullName ASC
Output
AdventureWork2016 db is used for work
Full Schema AW2016
There's definitely a certain way to think about use of hierarchyid that, once you get the hang of it, opens a lot of possibilities. Here's what I came up with:
WITH FullPerson AS (
SELECT CONCAT_WS(' ', p.FirstName, p.MiddleName, p.LastName) AS [FullName],
e.HireDate,
e.BirthDate,
e.OrganizationNode
FROM HumanResources.Employee AS e
JOIN Person.Person AS p
ON p.BusinessEntityID = e.BusinessEntityID
)
SELECT
manager.OrganizationNode.ToString(),
manager.FullName,
manager.HireDate,
manager.BirthDate,
subordinate.OrganizationNode.ToString(),
subordinate.FullName,
subordinate.HireDate,
subordinate.BirthDate
FROM FullPerson AS subordinate
JOIN FullPerson AS manager
ON subordinate.OrganizationNode.GetAncestor(1) = manager.OrganizationNode
WHERE manager.HireDate > subordinate.HireDate
AND manager.BirthDate > subordinate.BirthDate;
Breaking it down, I create a common table expression to join Employee and Person as I'll need columns from both tables for both subordinates and their managers. The real trick is the join condition. subordinate.OrganizationNode.GetAncestor(1) = manager.OrganizationNode says "take the subordinate's OrganizationNode and go one level up the tree". What's amazing to me is that this sort of query can be supported by indexes and indeed there is an index on that column in the AdventureWorks schema! In addition to the columns you asked for, I added a human-readable representation of OrganizationNode to help with the visualization of how the data relates.

How to find a destinct values in a table that are larger than all values that reference it?

I need to find the names of bosses who were hired after all the hired date of all their subordinates.
Here is what I have got so far:
SELECT DISTINCT
TRIM(boss.first_name || ' ' || boss.last_name) AS NAME,
boss.phone_number AS phone
FROM
HR.employees e
INNER JOIN HR.employees boss ON (boss.employee_id = e.manager_id)
WHERE
boss.hire_date > MIN(e.hire_date)
AND boss.hire_date > MAX(e.hire_date);
The idea was to check that the boss.hire_date is larger than the earliest and latest hire_date of his subordinates.
However I get following error message:
ORA-00934: group function is not allowed here
Any idea how I have to restructure the query?
What about using a subselect to get the maximum hire date of all employees for a given boss and check that in the WHEREclause?
You may need to filter this list for employees, that are not a boss.
Like:
SELECT boss.*
FROM hr.employees boss
WHERE boss.hire_date > (SELECT MAX(e.hire_date)
FROM hr.employees e
WHERE boss.employee_id = e.manager_id);
This should work better
SELECT TRIM(boss.first_name || ' ' || boss.last_name) AS NAME,
boss.phone_number AS phone
FROM HR.employees boss
INNER JOIN
(
SELECT e.manager_id, MAX(e.hire_date) AS Max_hire_date
FROM HR.employees e
GROUP BY e.manager_id
) m ON m.manager_id=boss.employee_id
WHERE boss.hire_date > m.Max_hire_date
Note that I have supposed that a boss can't manage itself. In an usual hierarchical database, the top manager has its manager_id field = NULL. If in your data a boss can have its manager_id =i ts own employee_id, it wont work.

Creating a sentence from multiple tables in SQL

I am trying to create this Result “Sabre is 12 years old” sentence using the code below in SQL.
select
businessname+' is ' + cast(count(e.id)as varchar(11))
from
Department d
join
EmployeeDepartmentHistory EDH on edh.departmentid = D.departmentid
join
employee e on edh.id = e.id
group by
name
+' years old'
If I were to run this section of the code
select
businessname+' is ' + cast(count(e.id)as varchar(11))
from
Department d
join
EmployeeDepartmentHistory EDH on edh.departmentid = D.departmentid
join
employee e on edh.id = e.id
group by
name
I will get "Sabre is 12"
But I am having a problem getting the "years old" string at the end.
I am getting this error message with the full code
Msg 8120, Level 16, State 1, Line 4
Column 'HumanResources.Department.Name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Without having some required information like:
The structure of the tables, which tables have what columns
How the tables are related to each other,
What you are trying to fetch (eg. what 'businessname' signifies here)
it becomes little difficult to provide proper suggestion.
So, assuming that:
EmployeeDepartmentHistory is the bridge table between Department
and Employee tables to take care of Many:Many relationship between
Department and Employee tables
One businessname (whichever table it belongs to) has
many employees (e.id) under it
You are trying to calculate the count of employees (e.id) for
each businessname,
This would be the right query:
SELECT businessname+' is ' + CAST(COUNT(e.id) AS VARCHAR(11)) + ' years old'
FROM Department d
JOIN EmployeeDepartmentHistory EDH on edh.departmentid=D.departmentid
JOIN employee e on edh.id=e.id
GROUP BY businessname

How to display last names and numbers of all managers together with the number of employees that are his/her subordinates

This is the schema
\,
I try using inners but the results were trash
SELECT
employees.last_name AS last_name,
COUNT(employees.job_id) AS EMPLOYEES_Subordinates,
COUNT(employees.manager_id) AS Manager_Numbers
FROM
employees left
JOIN departments ON departments.manager_id = employees.manager_id
GROUP BY
employees.last_name
ORDER BY
EMPLOYEES_Subordinates desc;
( i really don't know how to show you the tables from hr)
If any 1 has the HR in Oracle Database and have time to help me , I gladly appreciate .
not quite sure but try something like this:
SELECT
e.LAST_NAME
,(SELECT COUNT(ee.EMPLOYEE_ID) FROM EMPLOYEES ee WHERE ee.MANAGER_ID = e.EMPLOYEE_ID) AS 'NUMBER OF WORKERS'
FROM EMPLOYEES e
WHERE MANAGER_ID IS NULL

Sql Query! Can someone explain this?

Q1 : List employees who have the biggest salary in their departments
Q2 : List employees that don't have a boss in the same department
Q1 Answer)
Select e.name, Max_Sal.Sal
From Employees e
JOIN (Select d.DepartmentID,max(e.Salary) As Sal
From Employees e
JOIN Departments d ON e.DepartmentId=d.DepartmentId
Group by d.departmentID
) As Max_Sal
ON e.DepartmentId=Max_Sal.DepartmentID
and e.Salary=Max_Sal.Sal;
In Q2, I don't understand the question, [don't have a boss in the same department]. How to know boss is in which department?
Q2 : List employees that don't have a boss in the same department
There is a slight trick to this question.
1 - Join
SELECT e.*
FROM Employees e
LEFT OUTER JOIN Employees b on e.BossId = b.EmployeeId
Notice the following:
We've used the Employees table twice, but I've given them separate names. e is every employee; and b is that employee's boss.
We use a LEFT OUTER JOIN to account for the possibility that an employee does not have a boss (b will be NULL) If we had used an INNER JOIN, the employees with no boss would have been omitted from the result.
Now, we have a table of every employee, connected to their boss. But we still need to filter the list as requested.
2 - Filter
There are three possible states that an employee can be in:
They have no boss.
They have a boss, who works in the same department.
They have a boss, who works in a different department.
It's important to realize that the requested output needs to contain both the employees in situation 3 and the employees in situation 1. We should only omit the employees in situation 2.
Using pseudo-SQL, this means your query should look like this:
SELECT *
FROM the_data
WHERE
situation_1_applies
OR
situation_3_applies
The individual filters are not that hard to write:
SELECT e.*
FROM Employees e
LEFT OUTER JOIN Employees b on e.BossId = b.EmployeeId
WHERE
-- situation_1_applies
-- When b is NULL, all of b's columns are NULL
b.DepartmentId is NULL
OR
-- situation_3_applies
b.DepartmentId <> e.DepartmentId
Don't have a boss in the same department, so you can think bossID in Employees table is null. So you can write an SQL query for a group all of the people have the same department who have the bossID is null :), So it not real because employees have to have a boss (not null), If you show me full field of table, maybe I will show you exactly my answer.
In the other hand, you can think, They have the same bossID, so your mission will write an SQL query for a group all of the people have the same bossID but they have a different department.
I have an example MySQL query (for same bossID but different department):
SELECT * FROM Employees as e
INNER JOIN department d ON d.departmentId = e.deparmentId
WHERE e.DepartmentID in (
SELECT DepartmentID
FROM Employees
GROUP BY DepartmentID
HAVING COUNT(*) = 1 /* it's fixed */
) AND e.BossID = 2 /* any value of bossID you want, you can join it with Boss table */
===== Update my answer =====
I have an idea for the question.
Anyone must have a boss, and boss also is an employee in table SQL.
' employeeName ' department name ' boss name
--------------------------------------------------------
' King ' Director '
' Victor ' Marketing ' King
' Angela ' Product ' King
' Ken ' Marketing ' Victor
' LaLa ' Marketing ' Victor
' Jery ' Business ' Ken
And because don't have a boss in the same department -> their department can't have their boss. => the result as the following table:
' employeeName ' department name ' boss name
--------------------------------------------------------
' King ' Director '
' Victor ' Marketing ' King
' Angela ' Product ' King
' Jery ' Business ' Ken
If you have a right way to understand this question, you can post here for everyone can understand. Thanks