Kindly help to write SQL queries - sql

I need your help to write two SQL queries (DB Oracle) to fetch data. Both table has huge data so need to take care of the performance also. Below is the scenario -
There are two tables Department (DEPT) and Employee (EMP). They have a 1 (DEPT) : M (EMP) relationship.
Department table has columns
Row_id, DeptNm, Created_date
Employee table has columns
Row_id, EMPName, Emp_num, Par_row_id (FK to DEPT.row_Id), Salary
For a specific Department, sort data per employee's decreasing salary and rank it. Data should be shown like this:
DeptNm | EmpNm | Salary | Rank
--------------------------------
Finance | Vikram | 200000 | 1
Finance | Uttaam | 150000 | 2
Finance | Rajeev | 100000 | 3
ITDPPT | Balaajii | 150000 | 1
ITDEPT | Harsha | 120000 | 2
ITDEPT | Weeniji | 100000 | 3
Query that to show the data highest salary for a department. Data should be as -
Dept_Nm | EMP_NM | Salary
Finance | Vikramadit | 2000000
ITDEPT | Balaji | 1500000

select *
from (
select dp.deptname,
emp.empname,
emp.salary,
dense_rank() over (partition by dp.deptname order by emp.salary desc) as rnk
from employee emp
join department dp on dp.row_id = emp.par_row_id
) t
where rnk = 1

Try this will help you please put Rank as I didn't get what process you want if you want dynamic Rank than try any "temp" variable.
select D.DeptName,E.EmpName,E.Salary from Employee E
lefe join Department as D on D.Par_Row_Id=E.Row_Id order by E.Salaray DESC

select D.DeptName,E.EmpName,E.Salary from Employee E
left join Department as D on D.Par_Row_Id=E.Row_Id order by E.Salaray DESC

Related

Leetcode problem: Department Highest Salary

The Employee table holds all employees. Every employee has an Id, a salary, and there is also a column for the department Id.
+----+-------+--------+--------------+
| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1 | Joe | 70000 | 1 |
| 2 | Jim | 90000 | 1 |
| 3 | Henry | 80000 | 2 |
| 4 | Sam | 60000 | 2 |
| 5 | Max | 90000 | 1 |
+----+-------+--------+--------------+
The Department table holds all departments of the company.
+----+----------+
| Id | Name |
+----+----------+
| 1 | IT |
| 2 | Sales |
+----+----------+
Write a SQL query to find employees who have the highest salary in each of the departments. For the above tables, your SQL query should return the following rows (order of rows does not matter).
+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT | Max | 90000 |
| IT | Jim | 90000 |
| Sales | Henry | 80000 |
+------------+----------+--------+
My solution is below, Someone please tell me why this is not working
Select Department , Employee ,MAX(Salary) AS SALARY FROM
(select Department.Name AS Department,Employee.Name as Employee, SALARY from employee
LEFT JOIN Department
ON Employee.DepartmentID=Department.ID) as base
GROUP BY Department
The difference between my code output and expected output is given below.
Output
{"headers": ["Department", "Employee", "SALARY"], "values": [["IT", "Joe", 90000], ["Sales", "Henry", 80000]]}
Expected
{"headers": ["Department", "Employee", "Salary"], "values": [["IT", "Jim", 90000], ["Sales", "Henry", 80000], ["IT", "Max", 90000]]}
Someone please tell me why this is not working
Because what you have so far reads like this: "for every department, return an unspecified employee, and also return max salary within this department". Note that max salary is in no way related to the employee that is returned. In this case, it's seems to be returning the first employee for each department. And in case of "Sales", it even turns out to be correct, accidentally.
What you should have written is "for every department, find out its max salary. Then find all employees whose salary is equal to max_salary for their department"
You first need to get the MAX(SALARY) by Department and then query all employee that have this salary in this department.
-- max salary by department, adding DepartmentName to the result
WITH max_salary as (
SELECT Department.DepartmentId, Department.Name as DptName, MAX(SALARY)
FROM Employee JOIN Department
ON Employee.DepartmentID=Department.ID
GROUP BY DepartmentId, Name
)
-- select ALL employees with max salary
SELECT DptName, e.Name, e.SALARY
FROM Employee e JOIN max_salary m
ON e.SALARY=m.SALARY AND e.DepartmentId=m.DepartmentId
Get the highest SALARY for each department, and then return the employees whose salaries are equal to the maximum SALARY. The following query does this.
WITH TB_Salary as (
SELECT MAX(SALARY) AS Salary,DepartmentId
FROM employee
GROUP BY DepartmentId
)
SELECT DISTINCT Department.Name AS Department,employee.Name AS Employee,employee.Salary FROM employee
JOIN TB_Salary ON employee.SALARY = TB_Salary.SALARY AND employee.DepartmentId = TB_Salary.DepartmentId
JOIN Department ON Department.Id = employee.DepartmentId
ORDER BY employee.Salary DESC
OR
SELECT DISTINCT Department.Name AS Department,employee.Name AS Employee,employee.Salary
FROM employee
JOIN
(
SELECT MAX(SALARY) AS Salary,DepartmentId
FROM employee
GROUP BY DepartmentId
) TB_Salary
ON employee.SALARY = TB_Salary.SALARY AND employee.DepartmentId = TB_Salary.DepartmentId
JOIN Department ON Department.Id = employee.DepartmentId
ORDER BY employee.Salary DESC
output:

Case to get if the employee doesn't have an active employer, then give me a null employer

I have three tables: Employee, Employer, and Employment History. I'm looking to get a list of employees, with their most recent full-time employer, if they have an active full-time record.
Say I have the following Employment History table:
Employee ID | Employer ID | Start Date | End Date | Status
---------------------------------------------------------------
1 | AA | 1/1/2019 | | Part-Time
1 | BB | 1/1/2000 | | Full-Time
2 | CC | 3/1/2019 | | Part-Time
2 | DD | 3/1/2000 | 5/15/2021 | Full-Time
And Employees with IDs 1, 2, and 3.
Here's where I start:
select employee.id, employer.id
from Employee employee left join EmploymentHistory eh on eh.employeeId = employee.id
left join Employer employer on eh.employerId = employer.id
But I don't know how to say if the employee doesn't have an active employer, then give me a null employer ID. If they have an active (as in no end date) employment history record that is full-time, give me the most recent of those, and if they don't have an active full-time record, then give me the most recent part-time one.
I started going into loops with sub queries and trying to select based on max start date, and I'm all sorts of turned around.
In the end, I'd like the results to look something like this:
Employee ID | Employer ID
---------------------------
1 | BB |
2 | CC |
3 | <null> |
Is this possible?
You can try OUTER APPLY and a subquery that fetches the top record for each employee according to the type and end of the employment.
SELECT e.id,
x.employerid
FROM employee e
OUTER APPLY (SELECT TOP 1
eh.employerid
FROM employmenthistory eh
WHERE eh.employeeid = e.id
AND eh.status IN ('Full-Time',
'Part-Time')
ORDER BY eh.status ASC,
eh.enddate DESC) x;
I'm looking to get a list of employees, with their most recent full-time employer, if they have an active full-time record.
You can just use one table:
select eh.*
from (select eh.*,
row_number() over (partition by employee_id order by startdate desc) as seqnum
from EmploymentHistory eh
where status = 'Full-Time'
) eh
where seqnum = 1;

Oracle SQL: Divided one row to other row in other table without repatriation depending in variable value

I have tow table :
Customer :
name
-----
TOMMY
LOUIE
HUGO
OLLIE
DAVID
LEWIS
JACKSON
Employees :
name | stage
---------+---------
OLIVER | 1
NOAH | 1
ALFIE | 1
OSCAR | 2
NOAH | 2
OLIVER | 2
LEO | 2
In Employee I have two stages. In each stage can it have same employees or different, what I want to divide or distribute the customer to employee with two condition :
the customer in first stage must have different employee in second stage
each employee must have same number of customer in each stage and each customer must have 1 employee in each stage without repetition.
I have done the procedure with cursor that insert the result in different table but the problem it give wrong result that repeating the customer in stage 1 to the same employee in stage 2 (e.g NOAH take the same Customer )
CREATE PROCEDURE AUDIT_Customer AS
CURSOR Customer_STAGE1 IS SELECT * FROM (
select
s.name Customer_name
,t.name Employees_name
from (select name, row_number() over(order by name) as rn from Employees WHERE stage = 1 ) t
join (select name, row_number() over(order by name) as rn from Customer ) s
on mod(s.rn - 1, (select count(*) from Employees WHERE stage = 1)) = t.rn -1);
CURSOR Customer_STAGE2 IS SELECT * FROM (
select
s.name Customer_name
,t.name Employees_name
from (select name, row_number() over(order by name) as rn from Employees WHERE stage = 2 ) t
join (select name, row_number() over(order by name) as rn from Customer ) s
on mod(s.rn - 1, (select count(*) from Employees WHERE stage = 2)) = t.rn -1);
Begin
For y in Customer_STAGE1 Loop
Insert into Customer_Employee(Customer_name,Employees_name,RECIVE_DATE,stage)
Values (Y.Customer_name ,Y.Employees_name,sysdate,1) ;
End Loop ;
For y in Customer_STAGE2 Loop
Insert into Customer_Employee(Customer_name,Employees_name,RECIVE_DATE,stage)
Values (Y.Customer_name ,Y.Employees_name,sysdate,2) ;
End Loop ;
COMMIT;
End AUDIT_Customer;
the results :
Customer| Employees| stage
--------+--------- +---------
TOMMY | OLIVER | 1
LOUIE | OLIVER | 1
HUGO | NOAH | 1
OLLIE | NOAH | 1
DAVID | ALFIE | 1
LEWIS | ALFIE | 1
JACKSON | ALFIE | 1
TOMMY | OSCAR | 2
LOUIE | OSCAR | 2
HUGO | NOAH | 2
OLLIE | NOAH | 2
DAVID | OLIVER | 2
LEWIS | OLIVER | 2
JACKSON | LEO | 2
how i can solve it?
filter the second section of your procedure
this might help:
(select name, row_number() over(order by name) as rn from Employees WHERE stage = 2 and Employee.Name not in (select Employee.Name from Employee WHERE stage = 1))

How can I sum two rows from two different tables?

I am facing a problem in sql query. I am attaching the Schema.
The thing i want is. I want to generate a query that will produce result like below.
=======================================================================================
showroom_id | total_salary | total_expense | total_sold | balance
=======================================================================================
| 1 | 2000 | 8000 | 30000 | 20000
=======================================================================================
| 2 | 1000 | 4000 | 25000 | 20000
=======================================================================================
| 3 | 3000 | 7000 | 30000 | 20000
====================================================================================
I want to group by showroom id and sum the expense amount , staff salary, item's price and show them in each individual row. Then another column balance will show total_sold -( total_expanse + total_salary). How can I do the query?
select
s.id as showroom_id,
sal.amount as total_salary,
exp.amount as total_expense
-- not sure where to get total_sold amount?
from showroom as s
left outer join (
select sum(t.amount) as salary, t.showroom_id
from staff_salary as t
group by t.showroom_id
) as sal on sal.showroom_id = s.id
left outer join (
select sum(t.amount) as salary, t.showroom_id
from expense as t
group by t.showroom_id
) as exp on exp.showroom_id = s.id

Return name of the employee who having top salary with join

here is the situation. I have two tables, one is table Tbl_employ, second is tbl_details.
Tbl_employ
----------
id | name
1 | Ravi
2 | ram
3 | sham
4 | john
Tbl_details
-----------
id | salary | emp_id
1 | 500 | 1
2 | 200 | 2
3 | 400 | 3
4 | 501 | 4
I want to return the name of the employee who has top salary in tbl_detail.
What will be the join query for this condition?
Please suggest. Thanks in advance.
Perhaps:
SELECT TOP(1) name
FROM Tbl_employ e INNER JOIN Tbl_details d ON e.id = d.emp_id
ORDER BY d.salary DESC;
Essentially, this joins the two tables on the key fields (id and emp_id), returning only a single result (TOP(1)) that is the maximum salary row (ORDER BY d.salary DESC).
I appreciate the answer of #Max Vernon.
You can also do it by another way. Please try this
select t.name from (
select Distinct top 1 salary ,name
from Tbl_employ as E
left outer join Tbl_details as D on D.empid=E.id
order by salary desc
) as t
you can check it here SQL Fiddle