SQL Server Query - sql

An employee mapped with 2 supervisors for specific periods. I need to find the supervisor which the employee mapped maximum period.
Employee Mapped with the supervisor A from '01/01/2010' to '31/08/2010'
Mapped with the supervisor B from '01/09/2010' to '31/12/2010'
So the maximum period of the supervisor is 'A'
This should find using sql server query.

As no DDL has been posted as yet, this may or may not help.
Select e.EmployeeName,
s.SupervisorName,
es.StartDate,
es.EndDate,
EmpMaxDays.MaxDays as 'TotalNumberOfDaysAssigned'
From dbo.Employees e
Left Join dbo.EmployeeSupervisors es on es.EmployeeID = e.EmployeeId
Left Join
(
Select Max(DateDiff(day, es.StartDate, es.EndDate)) as 'MaxDays',
EmployeeId
From dbo.EmployeeSupervisor
Group By EmployeeId
)EmpMaxDays on es.EmployeeId = EmpMaxDays.EmployeeId
Left Join dbo.Supervisros s on es.SupervisorId = s.SupervisorId
Where DateDiff(day, es.StartDate, es.EndDate) = EmpMaxDays.MaxDays
And es.EmployeeId = EmpMaxDays.EmployeeId

I suggest you use rank partitioning. This way you can select where the rank = 1 (the correct match). See here.

Related

How to use refer to multiple id's when using JOINs in SQL

I try to display the number of reviews which an employee provided and the number of reviews which he received. I try to do something like this, but in my output table (3) I receive incorrect data. I believe that this happens due to the wrong reference:
pr.reviewer_id = e.employee_id
however, if I reference it like this:
pr.employee_id = e.employee_id
then nr_of_reviews_receieved is correct and nr_of_reviews_posted is not, and if I change it back it's vice versa. So, I need in one case to use one reference and in another a different one, but all in one query.
SELECT
e.employee_id,
CONCAT_WS(' ',employee_first_name, employee_last_name) AS full_name,
COUNT(pr.reviewer_id) AS nr_of_reviews_posted,
COUNT(pr.employee_id) AS nr_of_reviews_received
FROM
employee AS e
LEFT JOIN
performance_review AS pr ON pr.reviewer_id = e.employee_id
GROUP BY
employee_first_name, employee_last_name, e.employee_id
You have to sample the tables twice and join to the table each time
for example:
SELECT
e.employee_id,
CONCAT_WS(' ',employee_first_name, employee_last_name) AS full_name,
COUNT(pr.reviewer_id) AS nr_of_reviews_posted,
COUNT(pr2.employee_id) AS nr_of_reviews_received
FROM
employee AS e
LEFT JOIN
performance_review AS pr ON pr.reviewer_id = e.employee_id
LEFT JOIN
performance_review AS pr2 ON pr2.employee_id = e.employee_id
GROUP BY
Necessary columns ...

Single SQL query on many to many relationship using join

I have a simple database with few tables (and some sample columns)
Employee (ID, Title, Content)
Project (ID, Title)
ProjectEmployee(ID ,EMPLOYEE_ID,PROJECT_ID)
Need to find employee's whose don't have any project using join query
I am able to do it using subquery
select * from employee
where id not in (select id from project_employee);
The LEFT JOIN with NOT NULL give you the expected results.
select e.*
from employee e
LEFT JOIN project_employee pe on pe.id = e.id
where pe.id is not null;
This would be best implemented using not exists, joining is not the correct solution if you do not need to return any columns from the joined table.
select *
from employee e
where not exists (select * from project_employee pe where pe.id = e.id)

SQL Joins and Corelated subqueries with column data

I am facing an issue in terms of understanding the joins. Lets say for an example we have two tables employee and sales and now I have a query where we have sales of an employee using the id of the employee
select e.employeename
,s.city
,SUM(s.sales)
from employee e
left join (select sales,eid from sales) s on s.eid = e.id
group by 1,2
I'd like to understand why s.city wasn't showing up? and also would like to understand what is this concept called? Is it co related sub queries on Joins? Please help me down over here.
select
e.employeename
,s.city
,SUM(s.sales)
from employee e
left join (select sales,eid,city from sales) s on s.eid = e.id
group by 1,2
in the left join above you have to add city as well. The query Imagine select sales,eid,city from sales is a table itself and then from this table you are selecting city (your second column s.city) this will run error as your table doesn't have a city column yet.
It is much easier to use CTE (common table expressions than CTE's) You can also do the above question as
select
e.employeename
,s.city
,SUM(s.sales)
from employee e
left join sales as s
on e.id = s.id
group by 1,2
here I have added e.id = s.id instead of s.id = e.id it is better to reference the key of the main table first.
you could use CTE (although used when you have to do a lot of referencing but you can see how it works):
With staging as (
select
e.employeename
,s.city
,s.sales
from employee e
left join sales as s
on e.id = s.id
),
sales_stats as (
select
staging.employeename,
staging.city,
sum(staging.sales)
from staging
group by 1,2
#here you will select from staging again consider staging as a separate table so you will have to have all the columns in the staging that you want to use further. Also you will have to reference columns using staging.x
)
select * from sales_stats
-- here you could have combined the steps but I wanted to show you how cte works, Hope this works for you

Struggling with SQL subquery selection

I'm trying to answer a SQL question for revision purposes but can't seem to work out how to get it to work. The tables in question are:
The question is asking me to write an SQL command to display for each employee who has a total distance from all journeys of more than 100, the employee's name and the total number of litres used by the employee on all journeys (the number of litres for a journey is distanceInKm / kmPerLitre).
So far I've tried several variations of code beginning with:
SELECT
name, TravelCost.distanceInKm / Car.kmPerLitre AS "Cost in Litres"
FROM
Employee, Car, TravelCost
WHERE
Employee.id = TravelCost.employeeID
AND Car.regNo = TravelCost.carRegNo
It's at this point I get a bit stuck, any help would be greatly appreciated, thanks!
Never use commas in the FROM clause. Always use proper, standard, explicit JOIN syntax.
You are missing a GROUP BY and a HAVING:
SELECT e.name, SUM(tc.distanceInKm / c.kmPerLitre) AS "Cost in Litres"
FROM Employee e JOIN
TravelCost tc
ON e.id = tc.employeeID JOIN
Car c
ON c.regNo = tc.carRegNo
GROUP BY e.name
HAVING SUM(tc.distanceInKm) > 100;
Use Group By and Having Clause
SELECT NAME,
Sum(TravelCost.distanceInKm/ Car.kmPerLitre) AS "Cost in Litres"
FROM Employee
INNER JOIN TravelCost
ON Employee.id = TravelCost.employeeID
INNER JOIN Car
ON Car.regNo = TravelCost.carRegNo
GROUP BY NAME
HAVING Sum(distanceInKm) > 100
You need to JOIN all the tables and find sum of litres like this:
select
e.*,
sum(distanceInKm/c.kmPerLitre) litres
from employee e
inner join travelcost t
on e.id = t.employeeId
inner join car c
on t.carRegNo = c.regNo
group by e.id, e.name
having sum(t.distanceInKm) > 100;
Also, you need to group by id instead of just names as the other answers suggest. There can be multiple employees with same name.
Also, use explicit JOIN syntax instead of older comma based syntax. It's modern and clearer.
-- **How fool am I! How arrogant am I! I just thought `sum(tc.distanceInKm/c.kmPerLitre)`
-- may have a problem, since a employee may have multiple cars,and car's kmPerLitre is differenct.
-- However there is no problem, it's simple and right!
-- The following is what I wrote, what a bloated statement it is! **
-- calcute the total number of litres used by the employee on all journeys
select e.name, sum(Cost_in_Litres) as "Cost in Litres"
from (
select t.employeeID
-- calcute the litres used by the employee on all journeys group by carRegNo
, sum(t.distanceInKm)/avg(c.kmPerLitre) as Cost_in_Litres
from TravelCost t
inner join Car c
on c.regNo = t.carRegNo
where t.employeeID in
( -- find the employees who has a total distance from all journeys of more than 100
select employeeID
from TravelCost
group by employeeID
having sum(distanceInKm)> 100
)
group by t.carRegNo, t.employeeID
) a
inner join Employee e
on e.id = a.employeeID
group by e.id,e.name;

Calculate Percentage Of Certified Managers

I asked a similar question a few weeks ago, but now the requirements have changed.
Considering the following tables:
http://www.maroisconsulting.com/Temp/query.png
I need to create a query that returns the percentages of employees who are managers (Titles.IsManager) and who have a date in the Certified field (Employees.Certified). The results need to be grouped by the Group each store is in.
So far I have this:
SELECT d.GroupId,
Sum(d.cert_complete) AS SumOfcert_complete,
Count(d.cert_complete) AS CountOfcert_complete
FROM (SELECT DISTINCT
s.GroupId,
e.EmployeeID,
IIf(e.Certified Is Null,0,1) AS cert_complete
FROM
((Stores AS s
INNER JOIN EmployeeStores AS es ON s.StoreId = es.StoreId)
INNER JOIN Employees AS e ON es.EmployeeId = e.EmployeeID)
INNER JOIN Titles AS t ON e.TitleId = t.TitleId
) AS d
WHERE t.IsManager
GROUP BY d.GroupId;
And then this
SELECT q.GroupId,
(SumOfcert_complete/CountOfcert_complete)*100 AS percent_certified,
Groups.GroupName
FROM qryGroupCert_base AS q
INNER JOIN Groups ON q.GroupId = Groups.GroupId;
You can see in the first query where I added the Titles table.
1) I get prompted for the IsManager, although I don't know why
2) The results coming back are not different than before I added the IsManager
Anyone see what's wrong here?
Many thanks
Within your first query, you have this subquery which includes Titles aliased as "t":
(SELECT DISTINCT
s.GroupId,
e.EmployeeID,
IIf(e.Certified Is Null,0,1) AS cert_complete
FROM
((Stores AS s
INNER JOIN EmployeeStores AS es ON s.StoreId = es.StoreId)
INNER JOIN Employees AS e ON es.EmployeeId = e.EmployeeID)
INNER JOIN Titles AS t ON e.TitleId = t.TitleId
) AS d
Then, after the definition of the subquery, you have this WHERE clause:
WHERE t.IsManager
The problem is the "t" alias and IsManager column only exist within the the subquery --> they are unknown to the outer (parent) query. In cases where the Access database engine encounters something it doesn't recognize as an object name, function, literal value, or SQL keyword, it thinks that something must be a parameter ... so pops up the input box asking you to provide a value for the (IsManager) parameter.
I think you should move the WHERE clause inside the subquery definition.
SELECT d.GroupId,
Sum(d.cert_complete) AS SumOfcert_complete,
Count(d.cert_complete) AS CountOfcert_complete
FROM [SELECT DISTINCT
s.GroupId,
e.EmployeeID,
IIf(e.Certified Is Null,0,1) AS cert_complete
FROM
((Stores AS s
INNER JOIN EmployeeStores AS es ON s.StoreId = es.StoreId)
INNER JOIN Employees AS e ON es.EmployeeId = e.EmployeeID)
INNER JOIN Titles AS t ON e.TitleId = t.TitleId
WHERE t.IsManager = True
]. AS d
GROUP BY d.GroupId;
Perhaps you need to supply a criteria for t.IsManager, such as t.IsManager = TRUE. If the where clause doesn't have a value to set it equal to, Access probably isn't resolving it to the actual column, but thinks it's a query parameter.