Select highest value over multiple tables - sql

I have the following tables
Table Name : tHREmployee
EmployeID# Employee DepartmentID DesignationID DOB BasicPay
101 Ajith 101 102 10/Feb/1982 10000
102 Aarathy NULL 101 15/Mar/1981 15000
103 Aruna 102 NULL 20/Sep/1980 5000
104 Ambily 101 NULL 20/Sep/1980 5000
105 Anjaly NULL 101 20/Sep/1980 10000
106 Babitha 103 NULL 20/Sep/1981 20000
Table Name : tHRDepartment
DepartmentID# Code Department
101 500 Production
102 501 HR
103 502 Finance
105 503 Marketing
Table Name : tHRDesignation
DesignationID# Designation
101 Executive
102 Manager
How can I display employee details (Employee, Department, Designation, basicPay) for those employees who have highest basic pay for each department in sql?

In Oracle, this should help you
WITH CTE AS
(
SELECT DepartmentID , MAX(BasicPay) MAXPAY FROM tHREmployee
GROUP BY DepartmentID
)
SELECT E.EmployeID EMPid, E.Employee EMP_NAME , DPT.Department DPT_NAME,
DSG.Designation DSG_NAME, BASICPAY
FROM CTE, tHREmployee E,tHRDepartment DPT, Designation DSG
WHERE
E.BASICPAY = MAXPAY
AND E.DepartmentID = CTE.DepartmentID
AND E.DepartmentID = DPT.DepartmentID
AND E.DesignationID = DSG.DesignationID
In other DBs, something similar to this would help you:
SELECT E.EmployeID EMPid, E.Employee EMP_NAME , DPT.Department DPT_NAME,
DSG.Designation DSG_NAME, BASICPAY
FROM tHREmployee E,tHRDepartment DPT, Designation DSG
WHERE
E.DepartmentID = CTE.DepartmentID
AND E.DepartmentID = DPT.DepartmentID
AND E.DesignationID = DSG.DesignationID
AND E.BASICPAY IN
( SELECT MAX(EE.BASICPAY) FROM tHREmployee EE GROUP BY DPT.DepartmentID )

Select A.Employee,B.Department ,c.Designation,a.BAsicPay from Employee A inner join Department B on A.Department=B.DepartmentID left join Designation C on A.designationID=C.DesignationID inner join (Select DepartmentID,max(BasicPay) as BasicPay from Employee group by DepartmentID) as s2
on s2.DepartmentID=A.DepartmentID and A.BAsicPay=s2.BasicPAy

Related

Update using joins by finding the previous value in sql

I have two tables and I have to update the address field in the emp table by looking up in the emphistory table with previous value i.e USA for employee John
Table emp
EId ename sal Address AccountId
-------------------------------
101 John 100 U X12
102 Peter 500 Null X13
Table emphistory
emphisid EId AccountId Address Date (use row_number to find the second record for that eid and accountid)
-----------------------------------------------------
1 101 X12 U 11-01-2020 09:45:00
2 102 X13 Null 11-01-2020 09:46:00
3. 101 X12 USA 11-01-2020 09:30:00
I have to join the tables with account id and eid.
This works in Postgresql & Sql Server
UPDATE emp
SET Address = hist.Address
FROM (
SELECT h.EId, h.AccountId, h.Address
, ROW_NUMBER() OVER (PARTITION BY h.EId, h.AccountId
ORDER BY h.Date DESC) AS Rn
FROM emphistory h
JOIN emp e
ON e.EId = h.EId
AND e.AccountId = h.AccountId
WHERE h.Address IS NOT NULL
) hist
WHERE emp.EId = hist.EId
AND hist.Rn = 2

Found Output from three tables

I have three tables. 1. Emp, 2. Salary, 3. Commison.
EMP table have four column i.e.
ID Name Gender department.
101 Tarun M 10
102 Sahil M 10
103 Manju F 10
104 Dipika F 10
105 Parvinder M 20
106 Akhilesh M 20
107 Shanti F 20
108 Shivani F 30
109 Bhuvan M 30
110 babita F 30
Salary table have two column i.e
ID Salary .
101 3000
102 5420
103 8954
104 10000
105 8574
106 9965
107 9000
108 7500
109 9658
110 9800
Commison Table have two column i.e.
ID Commission.
101 2500
104 2000
107 3000
109 5000
Output will Be
ID Name Salary+Commision
101 Tarun 5500
102 Sahil 5420
103 Manju 8954
104 Dipika 12000
105 Parvinder 8574
106 Akhilesh 9965
107 Shanti 12000
108 Shivani 7500
109 Bhuvan 14658
110 babita 9800
Your query will look like this:
select e.id, e.name, s.salary + c.Commission as total
from salary s,
Commission c,
emp e
where e.id = s.id
and c.id = s.id
Assuming I've understood your question correctly, you would simply do the following:
SELECT
E.ID
,E.Name
,S.Salary + C.Commission
FROM Emp E
LEFT JOIN Salary S on E.ID = S.ID
LEFT JOIN Commission C on E.ID = C.ID
SELECT ID, Name, s.Salary + c.Commission AS Total FROM EMP e
INNER JOIN Salary s ON e.ID = s.ID
INNER JOIN Commison c ON s.ID = c.ID
Considering every employee has their entry in salary table,
SELECT
E.ID as ID
,E.Name as Name
,nvl(S.Salary,0) + nvl(C.Commission,0) as "Salary+Commision"
FROM Emp E INNER JOIN Salary S on E.ID = S.ID
LEFT JOIN Commission C on E.ID = C.ID
In case you think their might be some employee whose record are not loaded in salary table but you want them in your result.
SELECT
E.ID as ID,E.Name as Name,nvl(S.Salary,0) + nvl(C.Commission,0) as "Salary+Commision"
FROM Emp E LEFT JOIN Salary S on E.ID = S.ID
LEFT JOIN Commission C on E.ID = C.ID
In case you dont want to write "JOIN" -
SELECT
E.ID as ID
,E.Name as Name
,nvl(S.Salary,0) + nvl(C.Commission,0) as "Salary+Commision"
FROM Emp E ,Salary S,Commission C
WHERE E.ID = S.ID(+)
AND E.ID = C.ID(+)
Anything you can do but handle NULL value coming from Commision table as every employee will not be getting commision.

CTE to replace JOIN

Can I use CTE instead of the my code here ? Here are the two tables and my code .
tbl1
D_ID department employee name manager name
112 d01 john d Peter k
113 d01 Emily f kevin s
tbl2
Emp_id employee name D_ID
100 john d 112
200 peter k 112
800 Emily f 113
500 kevin s 113
My code below , what I did is I joined tbl1 with tbl2 on D_ID and employee name and then filter out the records where employee's emp_id > manager's emp_id .
DECLARE #level nvarchar(MAX) =
(
select X.D_ID ,x.employee_NAME, x.emp_ID as employee_id,
y.manager_name ,y.emp_id as manager_id
) + ' '
from (
select distinct b.d_id , a.emp_id as employee_id
from tbl1 a , tbl2 b
where a.d_id=b.d_id and a.employee_NAME=b.employee_NAME
) x ,
(
select distinct b.d_id , a.emp_id as manager_id
from tbl1 a , tbl2 b
where a.d_id=b.d_id and a.employee_NAME=b.manager_NAME
) Y
where x.department=y.department and x.employee_id>=y.manager_id
FOR XML PATH('')
)
IF #level IS NOT NULL
BEGIN
RAISERROR(' employee ID>manager_id: %s',16, 1, #level)
with log;
END;
DESIRED OUTPUT is below as Emily f's employee id is > than her manager's ID .
D_ID employee_NAME employee_id manager_name manager_id
113 Emily f 800 kevin s 500
I think you just need some joins:
select t1.d_id, t1.employee_name, te.emp_id,
t1.employee_name as manager_name, tm.emp_id as manager_id
from tbl1 t1 join
tbl2 te
on t1.employee_name = te.employee_name join
tbl2 tm
on t1.manager_name = tm.employee_name
where te.emp_id > tm.emp_id;
It is quite curious that you are using the names to connect the two tables. Normally, you would use the employee id for this purpose and look up the name using the id.

sql query for getting data from two related tables

I have two tables, employee and inventory. One employee can have zero or more inventories.
I would like to list employee information along with at most one inventory information
and count of inventories belongs to one employee.
employee table
emp_num last_name first_name
-----------------------------------
100 john smith
101 mike pet
102 jes lyoid
inventory table
inv_num emp_num
---------------------------
12 100
13 100
15 100
30 102
desired Output
emp_num last_name invnum count(inv_num)
--------------------------------------------------------------------------
100 john 12 3
101 mike - 0
102 jes 30 1
What sql query can I use in this case?
Try this:
SELECT emp_num, last_name, MAX(inv_num) AS invnum, COUNT(inv_num) AS inv_count
FROM employee e LEFT OUTER JOIN inventory i ON e.emp_num = i.emp_num
GROUP BY e.emp_num, e.last_name
You could do something like this
Select E.Emp_Num,
e.Last_name,
MIN(Inv_Num) AS OldestInv,
COUNT(Inv_Num) AS TotalInv
FROM Employee E
LEFT OUTER JOIN Inventory I
(E.Emp_Num = I.Emp_Num)
GROUP BY E.Emp_Num, E.Last_Name
This will give you the minimum invoice number and the total count. The left outer join is the key
SELECT
e.emp_num,
e.last_name,
IFNULL(MAX(i.inv_num),'-') AS 'invnum',
COUNT(i.inv_num) AS 'count(inv_num)'
FROM
employee e LEFT JOIN inventory i
ON e.emp_num = i.emp_num
GROUP BY
e.emp_num, e.last_name

select dept names who have more than 2 employees whose salary is greater than 1000

How would do the following in SQL
"select dept names who have more than 2 employees whose salary is greater than 1000" ?
DeptId DeptName
------ --------
1 one
2 two
3 three
EmpId DeptId Salary
----- ------ ------
121 1 2000
122 1 2000
123 1 5000
124 1 4000
131 2 2000
132 2 6000
133 2 1000
134 2 1000
125 3 1000
126 3 20000
RESULT: one
How about something like this?
SELECT D.DeptName FROM
Department D WHERE (SELECT COUNT(*)
FROM Employee E
WHERE E.DeptID = D.DeptID AND
E.Salary > 1000) > 2
SELECT DEPTNAME
FROM(SELECT D.DEPTNAME,COUNT(EMPID) AS TOTEMP
FROM DEPT AS D,EMPLOYEE AS E
WHERE D.DEPTID=E.DEPTID AND SALARY>1000
GROUP BY D.DEPTID
)
WHERE TOTEMP>2;
select min(DEPARTMENT.DeptName) as deptname
from DEPARTMENT
inner join employee on
DEPARTMENT.DeptId = employee.DeptId
where Salary > 1000
group by (EmpId) having count(EmpId) > =2
hope this helps
select DeptName from DEPARTMENT inner join EMPLOYEE using (DeptId) where Salary>1000 group by DeptName having count(*)>2
select D.DeptName from [Department] D where D.DeptID in
(
select E.DeptId from [Employee] E
where E.Salary > 1000
group by E.DeptId
having count(*) > 2
)
select deptname from dept_1
where exists
(
SELECT DeptId,COUNT(*)
FROM emp_1
where salary>1000
and emp_1.deptid=dept_1.deptid
GROUP BY DeptId
having count(*)>2)
1:list name of all employee who earn more than RS.100000 in a year.
2:give the name of employee who earn heads the department where employee with employee I.D
My main advice would be to steer clear of the HAVING clause (see below):
WITH HighEarners AS
( SELECT EmpId, DeptId
FROM EMPLOYEE
WHERE Salary > 1000 ),
DeptmentHighEarnerTallies AS
( SELECT DeptId, COUNT(*) AS HighEarnerTally
FROM HighEarners
GROUP
BY DeptId )
SELECT DeptName
FROM DEPARTMENT NATURAL JOIN DeptmentHighEarnerTallies
WHERE HighEarnerTally > 2;
The very early SQL implementations lacked derived tables and HAVING was a workaround for one of its most obvious drawbacks (how to select on the result of a set function from the SELECT clause). Once derived tables had become a thing, the need for HAVING went away. Sadly, HAVING itself didn't go away (and never will) because nothing is ever removed from standard SQL. There is no need to learn HAVING and I encourage fledgling coders to avoid using this historical hangover.