Found Output from three tables - sql

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.

Related

How to use GROUP BY when fetching values from More than one Table [duplicate]

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 4 months ago.
We have 2 Tables Employees and Department.
We want to show the maximum salary from each department and their corresponding employee name from the employee table and the department name from the department table.
Employee Table
EmpId | EmpName |salary |DeptId
101 shubh1 1000 1
101 shubh2 4000 1
102 shubh3 3000 2
102 shubh4 5000 2
103 shubh5 12000 3
103 shubh6 1000 3
104 shubh7 1400 4
104 shubh8 1000 4
Department Table
DeptId | DeptName
1 ComputerScience
2 Mechanical
3 Aeronautics
4 Civil
I tried doing it but was getting error
SELECT DeptName FROM Department where deptid IN(select MAX(salary),empname,deptid
FROM Employee
GROUP By Employee.deptid)
Error
Token error: 'Column 'Employee.EmpName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.' on server 4e0652f832fd executing on line 1 (code: 8120, state: 1, class: 16)
Can someone please help me.
select salary
,EmpName
,DeptName
from (
select e.salary
,e.EmpName
,d.DeptName
,rank() over(partition by e.DeptId order by e.salary desc) as rnk
from Employee e join Department d on d.DeptId = e.DeptId
) t
where rnk = 1
salary
EmpName
DeptName
4000
shubh2
ComputerScience
5000
shubh4
Mechanical
12000
shubh5
Aeronautics
1400
shubh7
Civil
Fiddle
Now that I know it's MS SQL Server, technically; we could use cross or outer Apply; it's a table value function not a join per say... but this will depend on the version of SQL Server; and if you want data if it doesn't exist in another
I find this the "Best" Design pattern to use for this type of query.
What the engine does is for each record in department, it runs a query for the employees Finding those in that department returning the 1 record having the max salary. With top we could specify with ties to return more than one. but we would need to know how to handle Ties of salary. Use top 1 with ties or order the results so you get the "Top" result you want.
Demo: dbfddle.uk
SELECT Sub.empName, Sub.Salary, D.DeptName
FROM Department D
CROSS Apply (SELECT Top 1 *
--(SELECT TOP 1 with Ties * -- could use this if we ties
FROM Employee E
WHERE E.DeptID = D.DeptID
ORDER BY Salary Desc) Sub --add additional order by if we don't want ties.
The cross apply gives us:
+---------+--------+-----------------+
| empName | Salary | DeptName |
+---------+--------+-----------------+
| shubh2 | 4000 | ComputerScience |
| shubh4 | 5000 | Mechanical |
| shubh5 | 12000 | Aeronautics |
| shubh7 | 1400 | Civil |
+---------+--------+-----------------+
Before window functions, before cross Apply or lateral... We'd write an inline view
It would get us the max salary for each dept, we then join that back to our base tables to find the employee within each dept with max salary...
Demo: DbFiddle.uk
SELECT E.*, D.*
FROM Employee E
INNER JOIN Department D
on E.DeptID = D.DeptID
INNER JOIN (SELECT MAX(SALARY) maxSal , DeptID
FROM Employee
GROUP BY DeptID) Sub
on Sub.DeptID = E.DeptID
and Sub.MaxSal = E.Salary
One has to do a join to get the department info an the employee info. However, we can eliminate the join for salarymax by using exists and correlation instead.
Demo DbFiddle.uk
SELECT E.*, D.*
FROM Employee E
INNER JOIN Department D
on E.DeptID = D.DeptID
WHERE EXISTS (SELECT MAX(Sub.SALARY) maxSal , Sub.DeptID
FROM Employee Sub
WHERE sub.DeptID=E.DeptID --correlation 1
GROUP BY Sub.DeptID
HAVING E.Salary = max(Sub.Salary)) --correlation 2
We could eliminate the last join too I suppose:
Demo: Dbfiddle.uk
SELECT E.*, (SELECT DeptName from Department where E.DeptID = DeptID)
FROM Employee E
WHERE EXISTS (SELECT MAX(Sub.SALARY) maxSal , Sub.DeptID
FROM Employee Sub
WHERE sub.DeptID=E.DeptID --correlation 1
GROUP BY Sub.DeptID
HAVING E.Salary = max(Sub.Salary)) --correlation 2
The top 3 give us this result:
+-----+---------+--------+--------+--------+-----------------+
| id | empName | salary | deptID | DeptID | DeptName |
+-----+---------+--------+--------+--------+-----------------+
| 101 | shubh2 | 4000 | 1 | 1 | ComputerScience |
| 102 | shubh4 | 5000 | 2 | 2 | Mechanical |
| 103 | shubh5 | 12000 | 3 | 3 | Aeronautics |
| 104 | shubh7 | 1400 | 4 | 4 | Civil |
+-----+---------+--------+--------+--------+-----------------+

SQL Query: Customer Table Contains Different type of EmpIDs and i want to get their name in a single row

I got a customer table and each customer has 4 different employeeID (tranieeID,RepresenterID,CoridatorID and ManagerID) I want to get all these employees name rather then their ID in single row.
CustomerTable
|CustomerID|CustomerName|tranieeID|RepresenterID |CoridatorID |ManagerID
------------------------------------------------------------------------
01 Mr T 100 101 102 103
EmployeeTable
EmpID | EmpName
---------------
100 Mr A
101 Mr B
102 Mr C
103 Mr D
What I need
CustomerID | CustomerName | tranieeName | RepresenterName | CoridatorName | ManagerName
----------------------------------------------------------------------------------------
01 Mr T Mr A Mr B Mr C Mr D
I did inner join but I got 4 Rows, is there any way to get all these with a single row?
Thank you for your help!
JOIN should work. I would recommend LEFT JOIN in case any of the values are not filled in:
select c.*,
et.empname as traineeName,
er.empname as RepresenterName,
ec.empname as CoridatorIDName,
em.empname as ManagerName
from customertable c left join
employeetable et
on c.traineeID = et.empid left join
employeetable er
on c.RepresenterID = et.empid left join
employeetable ec
on c.CoridatorID = ec.empid left join
employeetable em
on c.ManagerID = em.empid
You could use a correlated subquery in each instance, such as
select c.CustomerId, CustomerName,
(select Empname from EmployeeTable e where e.EmpID=c.TranieeId) TraineeName,
(select Empname from EmployeeTable e where e.EmpID=c.RepresenterId) RepresenterName,
... etc
from CustomerTable c

SQL Server basics - where clause

This is the code I have:
use TSQL2012
select
emp.empid, emp.firstname, emp.mgrid,
manager.firstname as manager_name,
sum(unique(emp.mgrid)) as Total
from
HR.Employees AS emp, HR.Employees as manager
where
emp.mgrid = manager.empid
go
And the result I am supposed to get is:
empid firstame mgrid manager_name Total
1 2 Don 1 Sara 1
2 3 Judy 2 Don 2
3 4 Yael 3 Judy 2
4 5 Sven 2 Don 2
5 6 Paul 5 Sven
6 7 Russell 5 Sven
7 8 Maria 3 Judy
8 9 Zoya 5 Sven
I can't get the last column (Total). Any help would be appreciated
One way of doing it is by the use of CROSS APPLY:
select emp.empid, emp.firstname, emp.mgrid, manager.firstname as manager_name,
x.cnt as Total
from Employees AS emp
inner join Employees as manager on emp.mgrid = manager.empid
cross apply (
select count(*)
from Employees AS e
where e.mgrid = emp.mgrid) AS x(cnt)
Demo here
Edit:
You can also use a CTE in this way:
;With C as (
select b.mgrid, count(*) as Total
from Employees as b
group by mgrid
)
select emp.empid, emp.firstname, emp.mgrid, manager.firstname as manager_name,
Total
from Employees AS emp
inner join Employees as manager on emp.mgrid = manager.empid
inner join C on emp.mgrid = C.mgrid
Demo here

Select highest value over multiple tables

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

Return multiple values in one column

I have two tables
Employee:
Empid Ename Eage Eadd Ephone
1 x 23 b 677
2 y 24 h 809
3 z 34 u 799
Department:
Did fkEmpid dname ddescription
123 1 test test
234 1 test1 test1
667 2 hello hello
Finally I want something like this
Ename Eage Eadd Ephone dname
x 23 b 677 test,test1
y 24 h 809 hello
z 34 u 799 null
Please help me with the SQL
It certainly would be nice to know the target RDBMS. But this question is asked so often so let's try and list'em all (at least popular ones) side by side.
For SQL Server:
SELECT e.Ename, e.Eage, e.Eadd, e.Ephone, d.dname
FROM Employee e LEFT JOIN
(
SELECT fkEmpid,
STUFF((SELECT ',' + dname
FROM Department
WHERE fkEmpid = t.fkEmpid
FOR XML PATH('')) , 1 , 1 , '' ) dname
FROM Department t
GROUP BY fkEmpid
) d
ON e.Empid = d.fkEmpid
Here is SQLFiddle demo
For Mysql, SQLite, HSQLDB 2.X:
SELECT e.Ename, e.Eage, e.Eadd, e.Ephone, d.dname
FROM Employee e LEFT JOIN
(
SELECT fkEmpid,
GROUP_CONCAT(dname) dname
FROM Department t
GROUP BY fkEmpid
) d
ON e.Empid = d.fkEmpid
Here is SQLFiddle demo (MySql)
Here is SQLFiddle demo (SQLite)
For Oracle 11g:
SELECT e.Ename, e.Eage, e.Eadd, e.Ephone, d.dname
FROM Employee e LEFT JOIN
(
SELECT fkEmpid,
LISTAGG (dname, ',') WITHIN GROUP (ORDER BY dname) dname
FROM Department t
GROUP BY fkEmpid
) d
ON e.Empid = d.fkEmpid
Here is SQLFiddle demo
For PostgreSQL 9.X:
SELECT e.Ename, e.Eage, e.Eadd, e.Ephone, d.dname
FROM Employee e LEFT JOIN
(
SELECT fkEmpid,
string_agg(dname, ',') dname
FROM Department t
GROUP BY fkEmpid
) d
ON e.Empid = d.fkEmpid
Here is SQLFiddle demo
Output in all cases:
| ENAME | EAGE | EADD | EPHONE | DNAME |
---------------------------------------------
| x | 23 | b | 677 | test,test1 |
| y | 24 | h | 809 | hello |
| z | 34 | u | 799 | (null) |
Considering RDBMS as SQL SERVER 2008
select E.Ename,E.Eage,E.Eadd,E.Ephone,D.dname
into Table1
from Employee E
left join Deparment D on E.Empid=D.fkEmpid
select t1.[Ename], t1.[Eage], t1.[Eadd], t1.[Ephone],
STUFF((
SELECT ', ' + t2.dname
FROM Table1 t2
WHERE t2.Ename = t1.Ename
AND t2.Eage=t1.Eage
AND t2.Eadd=t1.Eadd
AND t2.Ephone=t1.Ephone
FOR XML PATH (''))
,1,2,'') AS Names
FROM Table1 t1
GROUP BY t1.Ename,t1.[Eage], t1.[Eadd], t1.[Ephone];
SQL FIDDLE