Create view for multi relational tables sql-server? - sql-server

I want to create a view to display Department Name, Count of Employees, Total Salary and Count of Projects for this department
and here is my query but no data is returned:
SELECT d.[DeprtmentName] ,
count(e.[Id]) AS Employees,
sum(e.[Salary]) AS [Total Salary],
count(p.[Id]) AS Pojects
FROM [dbo].[Department] as d
join [dbo].[Employee] as e on d.id = e.[DeptId]
join [dbo].[ProjectEmployee] as p on e.id = p.[EmployeeId]
join [dbo].[Project] on p.[ProjectId] = [dbo].[Project].[Id]
group by (d.[DeprtmentName])

Related

display managerNames and EmployeesNames from employees table

I need to return two values from [empname] in (the EMPLOYEES) table
which displays
empname in a column --- and ---
their managersnames (empname) in the other column
which there is no managername in departments
when i write this code it returns blank values
select empname managername, deptname
from employees , departments
where departments.managerid=employees.empid
and
employees.empname ='arwa'
try starting with
select *
from employees
where empname ='arwa'
you'll see arwa's deptID is 3. You want to add deptID 3's employeename aliased as managername
so next join in your departments table:
select
e.*, managerID
from
employees e inner join
departments d on
e.deptID = d.deptID
where empname ='arwa'
you'll see arwa's department managerID is 7. You want to add managerID 7's employeename aliased as managername. Try:
select
e.empname , m.empname as managerName
from
employees e inner join
departments d on
e.deptID = d.deptID inner join
employees m on
d.managerID = m.empID
where e.empname ='arwa'
You need to use ANSI-92 style joins. They have been around for more than 25 years now. Also, be more explicit in your aliases to avoid accidents. This query should get you the data you are looking for.
select EmployeeName = e.empname
, DepartmaneName = d.deptname
, Manager = man.empname
from employees e
join departments d on d.deptid = e.deptid
join employees man on man.empid = d.managerid
where e.empname = 'arwa'
You can try this :
select e1.empname, e2.empname as Manager from employees e1
join departments on e1.deptid = departments.deptid
join employees e2 on departments.managerid=e2.empid
where e1.empname = 'arwa'

Inner join Giving columns Multiple values

I have Three Tables In Database
Table : Group
Id, Name
Table : doctor
Id ,DId, DoctorName,
Table : Ratio
Id , DId, UpLimit , downLimit.
When i inner join them , I am Getting duplicate Values to Uplimit and downlimit,,
Actually Group is related to doctors, One group id can have multple doctors,, so when i save some data with Group and doctor, it is saving to all the records with same data, uplimit downlimit varies with different doctors , but when i inner join dem its showing same to all doctors,, how to skip uplimit and downlimit how to write the Query..
Select A.Group , B.doctor , C.Uplimit, D.downlimit from Group A
inner join Doctor B
on A.id = B.id
inner join C ratio
on A.id = c.id
issue is When i separately check it with doctor id in doctor table it is showing only one record, when i inner join them its showing same data to all doctors to particular
how to join them??
Please use the DISTINCT clause after SELECT. This will filter the duplicates.
Select DISTINCT A.[Group] , B.doctor , C.Uplimit, D.downlimit
FROM Group A
inner join Doctor B
on A.id = B.id
inner join Ratio C
on B.id = C.id
It is good to avoid using the keywords as table/column names.
You Table Structure must be like
Table : Group
Id, Name
Table : doctor
Id ,DId(foreign key for group table), DoctorName
Table : Ratio
Id(Foreign Key for Doctor Table), UpLimit , downLimit.
Ratio Table is either missing a foreign key or a primary key, assuming Id of Ratio table is foreign key
Select A.Group , B.doctor , C.Uplimit, D.downlimit from Group A
inner join Doctor B
on A.id = B.Did
inner join ratio C
on B.id = c.id
This should give what you needed

Cannot get group by to work

I have two tables Employee and Office and OfficeID is a foreign key in Employee table. I need to find the number of employees in each office along with the rest of the office details like office city and employee first name. I have written the following query:
select o.OfficeID, o.City, o.State, o.Country, o.ZipCode, count(e.EmployeeID)
from Office o
inner join Employee e on o.OfficeID = e.OfficeID
group by o.OfficeID
On executing I get the following message -
Column 'Office.City' is invalid in the select list because it is not
contained in either an aggregate function or the GROUP BY clause.
How should I correctly use group by to solve this problem?
thanks
You either need to include all the non-aggregated columns in the select list in the group by:
select o.OfficeID, o.City, o.State, o.Country, o.ZipCode,
count(e.EmployeeID)
from Office o inner join
Employee e
on o.OfficeID = e.OfficeID
group by o.OfficeID, o.City, o.State, o.Country, o.ZipCode ;
Or, aggregate the Employee separately. Here is one method:
select o.*, e.cnt
from Office o inner join
(select e.OfficeId, count(*) as cnt
from Employee e
group by e.OfficeId
) e
on o.OfficeID = e.OfficeID;
This form is handy because you don't have the outer aggregation and can include whatever columns you like from Office in the select.
Another method uses cross apply:
select o.*, e.cnt
from Office o inner join
(select count(*) as cnt
from Employee e
where o.OfficeID = e.OfficeID
) e;
This is a bit shorter.
select o.OfficeID, o.City, o.State, o.Country, o.ZipCode, e.EmployeeID, e.FirstName, e.LastName , officeCnt.cnt
from Employee e
inner join (select OfficeId, count(*) as cnt from Employee group by OfficeId) as officeCnt
on e.OfficeID = officeCnt.OfficeID;
inner join Office o on e.OfficeID = o.OfficeID
You need to count in a subquery where you can apply group by

Retrieve all sales for customer

I'm trying to get list of customers and then group sales per customer, the code below works, but not how I want it to.
I'm really after each customer to display once then all sales per customer.
SELECT i.item, i.Qty, c.NAME, c.address, s.OrderNo, s.OrderDate
FROM CUSTOMERS c
LEFT JOIN Sales s
ON c.name = s.cust
LEFT JOIN Items i
on i.OrderNo = s.OrderNo
WHERE s.Cust IS not NULL
--SubQuery the summed value by customer from the sales table then join to that.
SELECT i.item, i.Qty, c.NAME, c.address, s.OrderNo, s.OrderDate, s.SUM_CUSTOMER_SALES_VALUE
FROM CUSTOMERS c
LEFT JOIN ( SELECT Cust, SUM(CUSTOMER_SALES_VALUE) AS SUM_CUSTOMER_SALES_VALUE FROM Sales GROUP BY Cust ) s
ON c.name = s.cust
LEFT JOIN Items i
on i.OrderNo = s.OrderNo
WHERE s.Cust IS not NULL

SQL Group, get First purchase, Last Purchase and last employee associated with last purchase

In my DB I have Customers, who make Purchases, and those purchases are then associated with an employee who assisted with that purchase. I have written a query below that will provide me with a list of customers with how many total purchases they have made, their first purchase and the last purchase. I also want the employee name associated with the last purchase?
Customer
-cstId
-cstName
Purchase
-cstId
-soldDate
-empId
Employee
-FirstName
-LastName
-empId
SELECT customer.cstName, MAX(purchase.soldDate) AS [Last Purchase], MIN(purchase.soldDate) AS [First Purhcase], COUNT(invTruck.invId)
AS [Total Purchases]
FROM customer INNER JOIN
purchase ON customer.cstId = purchase.cstId
INNER JOIN
employee ON purchase.empId = employee.empId
GROUP BY customer.cstName
Can you use a stored procedure? I usually fall back to memory tables for situations like this.
Declare #tblCust TABLE (
cstid int null,
cstName varchar(50) null,
lastpurchase datetime null,
firstpurchase datetime null,
empid varchar(50) null
)
Insert into #tblCust(cstid, cstname, lastpurchase, firstpurchase)
SELECT purchase.cstid, customer.cstName, MAX(purchase.soldDate) AS [Last Purchase],
MIN(purchase.soldDate) AS [First Purhcase]
FROM customer INNER JOIN
purchase ON customer.cstId = purchase.cstId
GROUP BY purchase.cstId, customer.cstName
Update t set EmpId = p.EmpId
From #tblCust t
INNER JOIN Purchase p ON t.cstId = p.cstid and t.LastPurchase = p.soldDate
You now have the employee id on a temp table that you can return your data from, or join to any other tables you may need.
I'm assuming you have some primary key on purchase table. I named it "purchaseID":
SELECT customer.cstName,
MAX(purchase.soldDate) AS [Last Purchase],
MIN(purchase.soldDate) AS [First Purhcase],
COUNT(invTruck.invId) AS [Total Purchases],
LastPurchase.empID AS [Last Purchase Employee]
FROM customer INNER JOIN
purchase ON customer.cstId = purchase.cstId
INNER JOIN
employee ON purchase.empId = employee.empId
CROSS APPLY (
SELECT TOP 1 *
FROM purchase px
WHERE px.purchaseID = purchase.purchaseID
ORDER BY px.soldDate DESC) AS LastPurchase
GROUP BY customer.cstName,
LastPurchase.empID
What the CROSS APPLY does is runs the enclosed select statement on every record, utilizing the WHERE criteria also inside. It behaves similarly to an INNER JOIN relative to an OUTER APPLY which behaves similarly a LEFT JOIN.
you could use APPLY: http://msdn.microsoft.com/library/ms175156(v=sql.105).aspx
use cross apply to get the list of purchases and the respective employee, with TOP 1 and sort by soldDate desc
example:
CROSS APPLY (
select top 1 p.empId
from purchase p
where p.cstId = customer.cstId
order by soldDate desc
) o (emp)
and add o.emp to your select
i'm not 100% sure that the syntax is 100% perfect but the idea is there :P
You can just extend it with a simple SCALAR SUBQUERY
SELECT
customer.cstName,
MAX(purchase.soldDate) AS [Last Purchase],
MIN(purchase.soldDate) AS [First Purhcase],
COUNT(invTruck.invId) AS [Total Purchases],
(SELECT TOP(1) e.lastname
FROM purchase p
INNER JOIN employee e ON p.empId = e.empId
WHERE customer.cstId = p.cstId
ORDER BY p.soldDate DESC) lastPurchaseEmployee
FROM customer
INNER JOIN purchase
ON customer.cstId = purchase.cstId
INNER JOIN employee
ON purchase.empId = employee.empId
GROUP BY
customer.cstId, customer.cstName

Resources