How to mark the Employee with highest salary with * ? - SQL Server - sql

I have a problem - here is my Employee table:
Name | Department | Salary
------+-------------+-------------
Ram |IT | 1000
Shyam |HR | 2000
Sita |Management | 5000
Joe |IT | 6000
Lacy |HR | 2000
Gen |Management | 4000
Maria |IT | 2000
Antony|HR | 3000
Raman |Management | 50000
Now I want the result like this:
Department | Salary |
-------------+------------+
IT | 20000
HR | 30000
Management | 50000 | *
Where * will be used to mark the max salary from any department. I've tried many unsucessful attempts, like :
Select
Salary,
Case
When Salary = Max(Salary) Then '*'
End
From
tblEmployees
Group By
Salary

You want a window function:
Select Department, max(Salary) as salary,
(case When max(Salary) = max(Max(Salary)) over ()
Then '*'
End)
from tblEmployees
group by department;

The IT department in your result should be 6000.
select Department,
salary = max_sal_dep,
highest_salary = IIF(max_sal_dep = max_sal_all, '*', null)
from
(
select Department,
max_sal_all = MAX(Salary) over (),
max_sal_dep = MAX(Salary) over (partition by Department order by Department),
the_row = row_number () over (partition by Department order by Salary desc)
from #t
) x where x.the_row = 1
order by x.max_sal_dep;

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:

How to generate custom sequence number in SQL Server within a select statement

I have a table with a employee data
EmployeeNum | Department | Salary
1000 | 1 | 400
1001 | 1 | 200
1002 | 2 | 350
1003 | 2 | 450
And I want to get sum of the salary by the department and the salary per employee in one select query. The expected output is
SQNO | EmployeeNum | Department | Salary
1 | 1000 | 1 | 400
2 | 1001 | 1 | 200
| | 1 | 600
3 | 1002 | 2 | 350
4 | 1003 | 2 | 450
| | 2 | 800
My approach is
select
case
when EmployeeNum is null
then null
else ROW_NUMBER() over (order by Department)
end as SQNO,
EmployeeNum,
Department,
SUM(Salary)
from
EMPDetails
group by
GROUPING sets(EmployeeNum, Department), (Department)
The output of this select is
SQNO | EmployeeNum | Department | Salary
1 | 1000 | 1 | 400
2 | 1001 | 1 | 200
| | 1 | 600
4 | 1002 | 2 | 350
5 | 1003 | 2 | 450
| | 2 | 800
Is there a way to skip row numbers as we desire or any other idea how to do this?.
Another possibility that returns what you want
DECLARE #T AS TABLE (EmployeeNum INT, Departement INT, Salary INT)
INSERT INTO #T VALUES (1000,1,400),(1001,1,200), (1002,2,350), (1003,2,450)
SELECT a.SQNO, a.EmployeeNum, a.Departement, a.Salary
FROM (
SELECT 1 AS dummy, ROW_NUMBER() OVER(ORDER BY DEPARTEMENT) SQNO, EmployeeNum, Departement, Salary
FROM #T
UNION
SELECT 2, NULL, NULL, Departement, SUM(Salary)
FROM #T
GROUP BY Departement
) AS a
ORDER BY Departement,a.dummy
You can do this with DENSE_RANK() and additional order by clause at the bottom:
select
case
when EmployeeNum is null
then null
else dense_rank() over (order by EmployeeNum)
end as SQNO,
EmployeeNum,
Department,
SUM(Salary)
from
EMPDetails
group by
GROUPING sets(EmployeeNum, Department), (Department)
order by department
Try this:
SELECT
emps.seqn,
emps.EmployeeNum,
CASE WHEN emps.Department IS NULL THEN outere.Department ELSE emps.Department END AS DEP,
CASE WHEN emps.salary IS NULL THEN outere.TOTALSUM ELSE emps.salary END AS salary
FROM (
SELECT *, row_number( ) over(order by Department, EmployeeNum) as seqn from EMPDetails
) emps
FULL JOIN (SELECT Department, SUM(salary) as TOTALSUM, -1 as a from EMPDetails GROUP BY Department) outere
ON emps.salary = outere.a
ORDER BY DEP, CASE WHEN EmployeeNum IS NOT NULL THEN EmployeeNum ELSE 9223372036854775807 END
Use CTE method to get tolal for each department :
;WITH CTE (_Id , SQNo , EmployeeNum , Departement , Salary ) AS
(
SELECT 0, ROW_NUMBER() OVER(ORDER BY DEPARTEMENT) SQNO, EmployeeNum,
Departement, Salary FROM your_table
UNION ALL
SELECT 1, NULL SQNO, NULL EmployeeNum, Departement, SUM(Salary) Salary
FROM your_table
GROUP BY Departement
)
SELECT SQNo , EmployeeNum , Departement , Salary
FROM CTE ORDER BY Departement,_Id ASC

How do i get max salary row , group by country

------------------------------------------------
country | salary | name | adress
------------------------------------------------
India | 10000 | ch1 | something
japan | 20000 | ch2 | nothing
india | 25000 | ch3 | hjsdj
japan | 30000 | ch4 | hjhjhj
I need to get max salary in japan and also in india with adress, name.
Have a sub-query that returns each country's max salary. Join with that result to get the users with that max salary.
select t1.*
from tablename t1
join (select country, max(salary) as max_salary
from tablename group by country) t2
on t1.country = t2.country and t1.salary = t2.max_salary
Will return both users if it's a tie (i.e. several users with same maximum salary.)
If by chance your DBMS supports ROW_NUMBER() OVER() function you may try
select * from
(select ROW_NUMBER() OVER(PARTITION BY country ORDER BY salary DESC) as rn
, country, salary as max_salary, name, adress
from tablename
) t
where rn = 1
Note, contrary to jarlh's query it will return only one arbitrary row of equal top salaries rows for the country.

Kindly help to write SQL queries

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

Guide me with this stored procedure or function

Manager | Employee |HireDate
----------------------------------------
ManagerA| EmpA |1/1/2012
managerA| EmpB |1/15/2012
ManagerB| Emp C |2/1/2012
ManagerA| Emp D |2/15/2012
ManagerB| Emp E |2/8/2012
The bonus amount for each manager is calculated based on how many recruits were hired that month.
ex. each Manager gets 1000 for first hire and 500 additional for every next.
Its almost like each record has a seed
Manager | Employee |HireDate | Seed
------------------------------------------------
ManagerA| EmpA |1/1/2012 | 1
managerA| EmpB |1/15/2012 | 2
ManagerB| Emp C |2/1/2012 | 1
ManagerA| Emp D |2/15/2012 | 1
ManagerB| Emp E |2/8/2012 | 2
and Bonus is a function of the seed as 1000+(seed-1)*500
I need help generating the seed .I am not sure if I should use a stored procedure to generate the seed or a function
eventually I want to generate a table as below
Manager | Employee |HireDate | Bonus
-------------------------------------------------
ManagerA| EmpA |1/1/2012 | 1000
managerA| EmpB |1/15/2012 | 1500
ManagerB| Emp C |2/1/2012 | 1000
ManagerA| Emp D |2/15/2012 | 1000
ManagerB| Emp E |2/8/2012 | 1500
To get the seed
Select
*
,ROW_NUMBER() Over(Partition By Manager, Year(HireDate), Month(HireDate) Order By HireDate) As Seed
From
YourTable
To get the bonus directly
Select
*
,1000 + (Seed - 1) * 500 As Bonus
From
(
Select
*
,ROW_NUMBER() Over(Partition By Manager, Year(HireDate), Month(HireDate) Order By HireDate) As Seed
From
YourTable
) T