I am having trouble with a SQL join question.
I have a table EMPLOYEE with EmpID, FirstName, LastName, Email, Phone
I have another table OTHERNAME with 2 fields "Name" & "OtherName".
This table contains lookup values such as "James", "Jim"; "Thomas", "Tom"; "Steven", "Steve".
I want to write a query which will return rows
EmpID, FirstName, LastName, Email, Phone, OtherName
where Employee.Firstname = OTHERName.Name
Select e.EmpID, e.FirstName, e.LastName, e.Email, e.Phone, o.OtherName
From Employee e
Left Outer Join OtherName o on e.FirstName = o.Name
From your comments it sounds like you actually want an outer join.
(From Comments) An outer join would return all employees, along with an Othername if there is one, otherwise Othername would be a null value which you could handle in code. An inner join limits the results to only employees with a matching record.
try this:
SELECT
e.EmpID
CASE
WHEN o.OtherName IS NOT NULL THEN OtherName
ELSE e.FirstName
END AS FirstName
,e.LastName
,e.Email
,e.Phone
,o.OtherName
FROM Employee e
LEFT OUTER JOIN OtherName o ON e.FirstName = o.Name
select e.EmpID, e.FirstName, e.LastName, e.Email, e.Phone, o.OtherName
from employee e,othername o
where e.FirstName=o.name
SELECT E.EmpId,
E.FirstName,
E.LastName,
E.Email,
E.Phone,
O.OtherName
FROM EMPLOYEE E
INNER JOIN OTHERNAME O
ON E.FirstName = O.Name
SELECT E.EmpID, E.FirstName, E.LastName, E.Email, E.Phone, O.OtherName
FROM Employee E
INNER JOIN Othername O
ON E.Firstname = O.Name
Should do the trick
Or, if you want all results, even those without "other name" values.
SELECT E.EmpID, E.FirstName, E.LastName, E.Email, E.Phone, O.OtherName
FROM Employee E
LEFT OUTER JOIN Othername O
ON E.Firstname = O.Name
You may use following SQL Command
SELECT EMPLOYEE.EmpID,
EMPLOYEE.FirstName,
EMPLOYEE.LastName,
EMPLOYEE.Email,
EMPLOYEE.Phone,
OTHERNAME.OtherName FROM EMPLOYEE INNER JOIN OTHERNAME ON EMPLOYEE.FirstName = OTHERNAME.Name
Related
I was trying to do my exercise to get an answer to this question,
--Which employee has processed most orders?
following the table below;
and in SQL the query became this monster
select e.employeeid, e.lastname, count(*) as 'aantal' from employee e
join orders o on e.EmployeeID = o.EmployeeID group by e.EmployeeID,
e.LastName having count(*) = (
select top 1 count(*) as 'aantal' from employee e
join orders o on e.EmployeeID = o.EmployeeID
group by e.FirstName
order by count(*) desc
)
my question is, is there really no other ways to get an answer from this:
select e.employeeid, e.lastname, count(*) as 'aantal' from employee
join orders o on e.EmployeeID = o.EmployeeID
group by e.EmployeeID, e.LastName
and then just find a maximum of these table??
like: max(and here query)
You probably can try this:
select e.employee_id, e.title, count(o.order_id) as c from orders o join employees e on e.employee_id = o.employee_id group by e.employee_id, e.title order by c desc;
Answer to my question.
This is just impossible in SQL
https://www.youtube.com/watch?v=8hyCpyhj8Jc&ab_channel=DaveSullivan
I'm having trouble visualizing how subqueries would look in the form of joins instead. In particular, the following SQL:
SELECT DISTINCT e.EmployeeID, e.LastName, e.FirstName
FROM Employees e
INNER JOIN Orders o ON e.EmployeeID = o.EmployeeID
WHERE EXISTS
(
SELECT c.Country
FROM Customers c
WHERE c.Country = e.Country
)
It would greatly be appreciated if I could receive some tips on what to do when I want to turn a statement with a subquery into a join instead.
You need to be careful about duplicates, but the transformation for EXISTS is quite direct:
SELECT DISTINCT e.EmployeeID, e.LastName, e.FirstName
FROM Employees e INNER JOIN
Orders o
ON e.EmployeeID = o.EmployeeID INNER JOIN
(SELECT DISTINCT c.Country
FROM Customers c
) c
ON c.Country = e.Country
This looks clean. In fact, it is not:
SELECT DISTINCT e.EmployeeID, e.LastName, e.FirstName
FROM Employees e
JOIN Orders o ON o.EmployeeID = e.EmployeeID
JOIN Customers c ON c.Country = e.Country
;
The point is that if there are more than one matching rows for orders and Customers, these will all cause a seperate copy of the Employee record to be merged. These will later have to be suppressed by theDISTINCT(the optimiser might catch this, or it might not)
The point is: you dont need a distinct, since you are only selecting columns from employee:
SELECT e.EmployeeID, e.LastName, e.FirstName
FROM Employees e
WHERE EXISTS(
SELECT * FROM Orders o
WHERE o.EmployeeID = e.EmployeeID
)
AND EXISTS(
SELECT * FROM Customers c
WHERE c.Country = e.Country
);
Or,in a more or less ugly style:
SELECT e.EmployeeID, e.LastName, e.FirstName
FROM Employees e
WHERE EXISTS(
SELECT c.Country
FROM Orders o
JOIN Customers c
ON o.EmployeeID = e.EmployeeID
AND c.Country = e.Country
);
I have this SQL which works fine
SELECT COUNT(*) AS total, e.FirstName, e.LastName
FROM [Messages] AS m
INNER JOIN Employees AS e ON m.SenderId = e.UserId
GROUP BY e.EmployeeId, e.FirstName, e.LastName
But I want to also have total unread messages as column.
How can I achieve this in SQL?
SELECT
COUNT(*) AS total,
COUNT(where m.isRead = false) AS totalUnreadMessages,
e.FirstName, e.LastName
FROM
[Messages] AS m
INNER JOIN
Employees AS e ON m.SenderId = e.UserId
GROUP BY
e.EmployeeId, e.FirstName, e.LastName
You are almost there, use a case expression to do conditional counting:
SELECT Count(*) as total,Count(case when m.isRead = false then 1 end) as totalUnreadMessage,
e.FirstName,e.LastName
FROM [Messages] as m
inner join Employees as e on m.SenderId=e.UserId
group by e.EmployeeId, e.FirstName,e.LastName
I would write this as:
SELECT e.FirstName, e.LastName, COUNT(*) as total,
SUM(CASE WHEN m.isRead = 0 THEN 1 ELSE 0 END) as total_unread
FROM [Messages] m JOIN
Employees e
ON m.SenderId = e.UserId
GROUP BY e.EmployeeId, e.FirstName, e.LastName;
You can count them then join them with the original select:
SELECT Count(*) as total,tbNotRead.NotReadNumber AS totalUnreadMessage, e.FirstName,e.LastName
FROM [Messages] as m
INNER JOIN Employees as e ON m.SenderId=e.UserId
LEFT OUTER JOIN
(
SELECT m.Sender, COUNT(*) NotReadNumber
FROM [Messages] msgs
WHERE m.isRead = FALSE
GROUP BY m.Sender
)tbNotRead
ON tbNotRear.Sender = m.sender
GROUP BY e.EmployeeId, e.FirstName,e.LastName, tbNotRead.NotReadNumber
I try to build a subquery with more than one column. Like this:
--SELF JOIN:
WITH Employees AS
(
SELECT
e.EmployeeID, e.ManagerID, e.Title,
c.FirstName + ISNULL(' ' + c.MiddleName,'') + ' ' + c.LastName AS EmpName
FROM
Employee AS e
INNER JOIN
Contact AS c ON e.ContactID = c.ContactID
)
SELECT
emp.EmployeeID, emp.ManagerID, emp.EmpName, emp.Title AS EmpTitle,
mgr.EmpName as MgrName, mgr.Title as MgrTitle
FROM
Employees AS Emp
INNER JOIN
Employees AS Mgr ON Emp.ManagerID = Mgr.EmployeeID;
--2
WITH Employees AS
(
SELECT
e.EmployeeID, e.ManagerID, e.Title,
c.FirstName + ISNULL(' ' + c.MiddleName,'') + ' ' + c.LastName AS EmpName
FROM
Employee AS e
INNER JOIN
Contact AS c ON e.ContactID = c.ContactID
)
SELECT
EmployeeID, ManagerID, EmpName, Title
FROM
Employees
WHERE
EmployeeID IN (SELECT EmployeeID, er2.MaritalStatus
FROM Employees AS e
INNER JOIN AdventureWorks2012.HumanResources.Employee AS er2 ON e.ManagerID = er2.BusinessEntityID
WHERE er2.MaritalStatus = 'M');
I want also to show the MarialStatus. But I can't do it this way, because I get the error:
Only one expression can be specified in the select list when the
subquery is not introduced with EXISTS.
But If I can't do it with exists in the subquery. So my question is: what is the proper way that I can select more then one column in the subquery?
Thank you
You can't return 2 values in a sub query.So you will have to remove the MaritalStatus column. That's the problem with your query.
USE tempdb;
WITH
Employees AS(
SELECT e.EmployeeID, e.ManagerID,e.Title,
c.FirstName + ISNULL(' ' + c.MiddleName,'') + ' ' + c.LastName AS EmpName
FROM Employee AS e
INNER JOIN Contact AS c
ON e.ContactID = c.ContactID
)
SELECT emp.EmployeeID, emp.ManagerID, emp.EmpName, emp.Title AS EmpTitle,
mgr.EmpName as MgrName, mgr.Title as MgrTitle
FROM Employees AS Emp INNER JOIN Employees AS Mgr
ON Emp.ManagerID = Mgr.EmployeeID;
--2
WITH Employees AS (
SELECT e.EmployeeID, e.ManagerID,e.Title,
c.FirstName + ISNULL(' ' + c.MiddleName,'') + ' ' + c.LastName AS EmpName
FROM Employee AS e
INNER JOIN Contact AS c
ON e.ContactID = c.ContactID)
SELECT e.EmployeeID, e.ManagerID, e.EmpName, e.Title,er2.MaritalStatus
FROM Employees e
INNER JOIN AdventureWorks2012.HumanResources.Employee AS er2
ON e.ManagerID = er2.BusinessEntityID
WHERE er2.MaritalStatus = 'M');
I don't think you need a subquery there,because INNER JOIN will give you only records if there's a match. So do a INNER JOIN fro the table and put the MaritalStatus column in the select clause
The problem appears to be in your second query. The second column is not necessary in the SELECT. But, you can further simplify the logic by removing the JOIN:
SELECT e.EmployeeID, e.ManagerID, e.EmpName, e.Title
FROM Employees e
WHERE e.ManagerID IN (SELECT er2.BusinessEntityID
FROM AdventureWorks2012.HumanResources.Employee er2
WHERE er2.MaritalStatus = 'M'
);
I have a query that I need to execute that I do not know how to structure.
I have a table called Employees. I have another table called Company. There is a third table called Files. As you can imagine, a Company has Employees, and Employees have Files.
I need to list out all of the Employees in my database. The challenge is, I need to list the total number of Files in the same company as the Employee. I have tried variations on the following without any luck:
SELECT
e.FirstName,
e.LastName,
e.Company,
(SELECT COUNT(*) FROM Files f WHERE f.EmployeeID IN (SELECT [ID] FROM Employees e2 WHERE e2.CompanyID=e.CompanyID)) as 'FileCount'
FROM
Employees e
What am I doing wrong? Thank you!
Try this:
SELECT
e.FirstName,
e.LastName,
e.Company,
(
SELECT COUNT(*)
FROM Files f
JOIN Employees e2 ON f.EmployeeID = e2.id
WHERE e2.CompanyID = e.CompanyID
) as 'FileCount'
FROM
Employees e
There are a lot of ways to get that. If the performance is a concern, this is more optimal according to estimated execution plan costs.
SELECT
e.FirstName,
e.LastName,
e.Company,
COUNT(f.FileId)
FROM
Employees e
INNER JOIN Files f ON e.EmployeeID = f.EmployeeID
GROUP BY
e.FirstName,
e.LastName,
e.Company
A solution with no correlation in SELECT clause. Probably quicker...
SELECT
e.FirstName,
e.LastName,
e.Company,
foo.FileCount
FROM
Employees e
JOIN
(
SELECT
COUNT(*) AS FileCount, --OR COUNT(DISTINCT something) ?
e2.Company, f.EmployeeID
FROM
Files f JOIN Employees e2 ON f.EmployeeID = e2.id
GROUP BY
e2.Company, f.EmployeeID
) foo ON e.Company = foo.Company AND e.id = foo.EmployeeID
How about:
SELECT
e.FirstName,
e.LastName,
e.Company,
select count(*) from Files f, Employees e where f.EmployeeID=e.EmployeeID and e.CompanyID=emp.CompanyID
FROM
Employees emp
WITH FilesPerCompany (CompanyID, NumberOfFiles)
AS (SELECT c.ID AS CompanyID,
COUNT(*) AS NumberOfFiles
FROM Companies c
INNER JOIN Employees e ON c.ID = e.CompanyID
INNER JOIN Files f ON e.ID = f.EmployeeID
GROUP BY c.ID
)
SELECT e.FirstName,
e.LastName,
e.Company,
COALESCE(s.NumberOfFiles, 0) AS NumberOfFilesPerCompany
FROM Employees e
LEFT JOIN FilesPerCompany s
ON s.CompanyID = e.CompanyID
The following statement uses recursive joins to iterate down employees who manage other employees who manage other employees .... etc. Our structure is a little convoluted as the management structure is role based which actually allows an employee to have more than 1 manager. You can add a reference to Files within this recursion.
WITH Manager as
(SELECT c.Forenames + ' ' + c.Surname as Employee,
c2.Forenames + ' ' + c2.Surname AS Manages,
c.accountid AS AccountID, c.[Status] AS [Status]
FROM [intranet].[dbo].[tblContact] c
LEFT JOIN tblContactPost cp ON cp.contactid = c.contactid
LEFT JOIN tblPost p ON p.ParentRoleId = cp.RoleID AND p.ParentPostArea = cp.PostArea AND p.ParentPostNo = cp.PostNo
INNER JOIN tblContactPost cp2 ON cp2.RoleId = p.RoleId AND cp2.PostArea = p.PostArea AND cp2.PostNo = p.PostNo
INNER JOIN tblContact c2 ON c2.ContactID = cp2.ContactId
)
,jn AS
(SELECT Employee, Manages
FROM Manager
Where AccountID = 'ad\lgardner' AND [Status] = 'A'
UNION ALL
SELECT c.Employee, c.Manages
FROM jn as p JOIN Manager AS c
ON c.Employee = p.Manages
)
SELECT jn.Employee, jn.Manages
From jn
Order BY 1