Right Outer join issue - sql

I've two tables that I want to join and filter data from. I used a stored procedure to do that. My intention is to bring every item from the second table (i.e Department) even if they don't have a matching record in the first table (i.e. Employee) and finally display the count. Here is the segment of the code I used:
select d.deptName,
case when COUNT(*) is null then '0' else count(*) end AS total
from Employee e
right outer join Department d on e.deptID=d.deptID
WHERE e.Year=#year
and e.Month=#month
group by d.deptName
order by d.deptName
But, it's not displaying what i wanted and failed to figure out the real problem.

When you apply the filter condition through where clause after join, it filters out all the records which doesn't satisfy the filter criteria. Try moving your filter criteria in join condition itself as below:
select d.deptName,
case when COUNT(*) is null then '0' else count(*) end AS total
from Employee e
right outer join Department d
on (e.Year=#year
and e.Month=#month
and e.deptID=d.deptID)
group by d.deptName
order by d.deptName

I think you need to change the code like this
SELECT d.deptName, COUNT(e.deptID) AS total
FROM Employee e
RIGHT OUTER JOIN Department d
ON (e.Year= #year
AND e.Month= #month
AND e.deptID=d.deptID)
GROUP BY d.deptName
ORDER BY d.deptName
See the SQL Fiddle for the query : http://sqlfiddle.com/#!3/b1105/17

Related

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

Not able to Fetch data, Using where clause to the result of union clause

I Need to fetch data form two tables from the result i get from union clause and to the result i have one more where clause added
select * from (select a.empid,a.department from EMPLOYEE a
union
select b.empid,b.empname from employeedetails b) t where a.empid=1;
I am getting this error.
a is not defined in the outer query. t is:
where t.empid = 1;
This UNION won't do what you want because you are mixing different columns.
In your case the result of your query will be 2 rows where in the 1st row you will have the employee's id and the department and in the 2nd row the employee's id and name.
What you need is a join:
select e.empid, e.department, d.empname
from EMPLOYEE e inner join employeedetails d
on d.empid = e.empid
where e.empid = 1

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;

Eliminate duplicate rows from query output

I have a large SELECT query with multiple JOINS and WHERE clauses. Despite specifying DISTINCT (also have tried GROUP BY) - there are duplicate rows returned. I am assuming this is because the query selects several IDs from several tables. At any rate, I would like to know if there is a way to remove duplicate rows from a result set, based on a condition.
I am looking to remove duplicates from results if x.ID appears more than once. The duplicate rows all appear grouped together with the same IDs.
Query:
SELECT e.Employee_ID, ce.CC_ID as CCID, e.Manager_ID, e.First_Name, e.Last_Name,,e.Last_Login,
e.Date_Created AS Date_Created, e.Employee_Password AS Password,e.EmpLogin
ISNULL((SELECT TOP 1 1 FROM Gift g
JOIN Type t ON g.TypeID = t.TypeID AND t.Code = 'Reb'
WHERE g.Manager_ID = e.Manager_ID),0) RebGift,
i.DateCreated as ImportDate
FROM #EmployeeTemp ct
JOIN dbo.Employee c ON ct.Employee_ID = e.Employee_ID
INNER JOIN dbo.Manager p ON e.Manager_ID = m.Manager_ID
LEFT JOIN EmployeeImp i ON e.Employee_ID = i.Employee_ID AND i.Active = 1
INNER JOIN CreditCard_Updates cc ON m.Manager_ID = ce.Manager_ID
LEFT JOIN Manager m2 ON m2.Manager_ID = ce.Modified_By
WHERE ce.CCType ='R' AND m.isT4L = 1
AND CHARINDEX(e.first_name, Selected_Emp) > 0
AND ce.Processed_Flag = #isProcessed
I don't have enough reputation to add a comment, so I'll just try to help you in an answer proper (even though this is more of a comment).
It seems like what you want to do is select distinctly on just one column.
Here are some answers which look like that:
SELECT DISTINCT on one column
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?

Sum a column that corresponds a aggregate from a column of another table

Sorry about the title, but i couldn't think of a better subject for my issue.
I've two tables in a many-to-one relationship between them and an other many-to-one relatioshop in the same table. I need to sum a column that corresponds a aggregate from a column of first table.
Here is a image that illustrate what i want:
I have no idea how to proceed with this.
This should do:
SELECT ISNULL(E.idParent,E.id) Id,
SUM(I.Value) [Sum]
FROM EXPENSE_TABLE E
LEFT JOIN INVOICE_TABLE I
ON I.idExpense = E.id
GROUP BY ISNULL(E.idParent,E.id)
For the updated requirement:
SELECT ISNULL(E.idParent,E.id) Id,
E2.[description],
SUM(I.Value) [Sum]
FROM EXPENSE_TABLE E
LEFT JOIN INVOICE_TABLE I
ON I.idExpense = E.id
INNER JOIN EXPENSE_TABLE E2
ON ISNULL(E.idParent,E.id) = E2.id
GROUP BY ISNULL(E.idParent,E.id),
E2.[description]
You can get the results you are looking for by performing the aggregate sum operation on the results of the EXPENSE_TABLE joined to the INVOICE_TABLE.
For example:
SELECT e.idParent, SUM(i.value)
FROM EXPENSE_TABLE AS e
INNER JOIN INVOICE_TABLE AS i ON i.idExpense = e.id
GROUP BY e.idParent
ORDER BY e.idParent