So basically I'm trying to replicate this query as a stored procedure.
Use ThisDB
SELECT FirstName + ' ' + LastName as FullName ,
sum(UnitPrice * Quantity) as 'Total Sales',
YEAR(OrderDate) as SalesYear
From Employees e
Join Orders o on o.EmployeeID = e.EmployeeID
join [Order Details] od on od.OrderID = o.OrderID
Group by LastName +' ' +FirstName, YEAR(OrderDate)
Order by 'Total Sales' desc
Edit: I noticed that the old query was gonna fail, but that don't change too much /edit
Unfortunately, I haven't found any good examples that help me translate what I know about queries to stored procedure syntax. Here is what i understand so far:
Use ThisDB;
go
CREATE PROCEDURE empSalesByYear as #Emp OUT
BEGIN
Set Emp = (SELECT Employees.FirstName, Employees.LastName ,
TotalSales = sum([Order Details].UnitPrice * [OrderDetails].Quantity),
YEAR(orders.OrderDate) as SalesYear
From Employees e
Join Orders o on o.EmployeeID = e.EmployeeID
join [Order Details] od on od.OrderID = o.OrderID
group by FirstName , LastName
Order by TotalSales desc)
END
GO
Predictably, SQL server give me the finger when I type all this in. . .
My goal here is a stored procedure that takes zero input parameters and outputs a table like the first query.
Thanks.
Further to my comment, you can just do:
CREATE PROCEDURE proc_GetEmpSalesByYear AS
SELECT FirstName + ' ' + LastName as FullName ,
sum(UnitPrice * Quantity) as 'Total Sales',
YEAR(OrderDate) as SalesYear
From ThisDB..Employees e
Join ThisDB..Orders o on o.EmployeeID = e.EmployeeID
join ThisDB..[Order Details] od on od.OrderID = o.OrderID
Group by LastName, FirstName Order by 'Total Sales' desc
GO
..unless you wanted to return a table output parameter?
(Removed the USE, missed that.. now using db..table format)
Related
I have 3 tables in SQL Server:
Sales (customerId)
Customer (customerId, personId)
Person (personId, firstName, lastName)
and I need to return the top 10 customers.
I used this query:
SELECT TOP 10
CustomerID, COUNT(CustomerID)
FROM
Sales
GROUP BY
(CustomerID)
ORDER BY
COUNT(CustomerID) DESC
The query currently returns only the customerId and count, but I also need to return the firstName and lastName of these customers from the Person table.
I know I need to reach the firstName and lastName by correlating between Sales.customerId and Customer.customerId, and from Customer.personId to get the Person.personId.
My question is whether I need to use an inner join or union, and how to use either of them to get the firstName and lastName of these customers
Union is mostly used for disjoint sets. To achieve your target, u can go with inner-join.
If you want to use joins, then here is the query which works similarly to your requirement.
SELECT TOP 10 S.CustomerID, P.FirstName,P.LastName, count(*)
FROM Sales S
INNER JOIN Customer C on S.CustomerId=C.CustomerId
INNER JOIN Person P on C.PersonId = P.PersonId
GROUP BY (S.CustomerID, P.FirstName,P.LastName)
ORDER BY count(*) DESC
You need use inner join like this :
SELECT TOP 10 S.CustomerID
, P.FirstName
, P.LastName
, COUNT (1) AS CountOfCustomer -- this is equal count(*)
FROM Sales S
INNER JOIN Customer C ON S.CustomerId = C.CustomerId
INNER JOIN Person P ON C.PersonId = P.PersonId
GROUP BY S.CustomerID, P.FirstName, P.LastName
ORDER BY 4 DESC; -- this is equal order by count(*)
I work with the AventureWorks2014 database in Microsoft SQL Server. I need to create a view that will show the CustomerID, the full name and the TOTAL amount sold to client through the web.
My problem is that I can't seem to get the values corresponding to a single customer add up so that a single customer answers to a single line in my result. This is the code I have, any help would be appreciated. I basically need to show the total amount sold to clients on the web.
if object_id('vTotalWebSalesPerCustomer', 'v') is not null
drop view vTotalWebSalesPerCustomer;
go
create view vTotalWebSalesPerCustomer
as
select distinct
c.CustomerID,
ltrim(rtrim(concat(concat(concat(concat(concat(concat(concat(p.Title, ' '), p.LastName), ', '), ' '), p.FirstName), ' '), p.Suffix))) as NomClient,
soh.TotalDue
from
[Sales].[Customer] as c
left join
[Person].[Person] as p on c.CustomerID = p.BusinessEntityID
left join
[Sales].[SalesOrderHeader] as soh on soh.CustomerID = c.CustomerID
where
year(soh.OrderDate) = 2014
and datepart(quarter, soh.OrderDate) = 1
and [OnlineOrderFlag] = 1
go
select *
from vTotalWebSalesPerCustomer
Thanks
Sounds like you need to use GROUP BY and SUM(), example:
SELECT column-names
FROM table-name
WHERE condition
GROUP BY column-names
ORDER BY column-names
Such as:
SELECT SUM(O.TotalPrice), C.FirstName, C.LastName
FROM [Order] O JOIN Customer C
ON O.CustomerId = C.Id
GROUP BY C.FirstName, C.LastName
ORDER BY SUM(O.TotalPrice) DESC
Would return:
Sum FirstName LastName
117483.39 Horst Kloss
115673.39 Jose Pavarotti
113236.68 Roland Mendel
57317.39 Patricia McKenna
52245.90 Paula Wilson
34101.15 Mario Pontes
32555.55 Maria Larsson
DISTINCT filters result rows to remove duplicates. What I think you want is to aggregate rows. Perhaps this will do what you want:
create view vTotalWebSalesPerCustomer as
select c.CustomerID,
ltrim(rtrim(concat(concat(concat(concat(concat(concat(concat(p.Title, ' '), p.LastName), ', '), ' '), p.FirstName), ' '), p.Suffix))) as NomClient,
sum(soh.TotalDue) as TotalDue
from [Sales].[Customer] as c
left join [Person].[Person] as p on c.CustomerID = p.BusinessEntityID
left join [Sales].[SalesOrderHeader] as soh on soh.CustomerID = c.CustomerID
where year(soh.OrderDate) = 2014 and datepart(quarter, soh.OrderDate)=1 and [OnlineOrderFlag] = 1
group by c.CustomerID,NomClient
Note that I removed distinct, added sum operator on the amount you want to total, and group by the customer id and name fields (SQL Server requires that you list in the GROUP BY all result columns which are not being aggregated).
You can use the following VIEW using a GROUP BY on the SELECT:
IF OBJECT_ID('vTotalWebSalesPerCustomer', 'v') IS NOT NULL
DROP VIEW vTotalWebSalesPerCustomer;
GO
CREATE VIEW vTotalWebSalesPerCustomer AS
SELECT
x.CustomerID,
LTRIM(RTRIM(CONCAT(p.Title, ' ', p.LastName, ', ', p.FirstName, ' ', p.Suffix))) AS NomClient,
x.TotalDue
FROM (
SELECT
c.CustomerID AS CustomerID,
SUM(soh.TotalDue) AS TotalDue
FROM [Sales].[Customer] AS c
LEFT JOIN [Sales].[SalesOrderHeader] AS soh ON soh.CustomerID = c.CustomerID
WHERE YEAR(soh.OrderDate) = 2014 AND DATEPART(quarter, soh.OrderDate) = 1 AND [OnlineOrderFlag] = 1
GROUP BY c.CustomerID
)x LEFT JOIN [Person].[Person] AS p ON x.CustomerID = p.BusinessEntityID
GO
Note: You only need one CONCAT function to concat all string values.
i want to Write a query using the temporary date table to show rows for every customer for every month since the month they first purchased from us. The table should detail the customer ID, customer name, month, Date of first Purchase, Units Purchased that month, Value Purchased that month, Cumulative Units Purchased, Cumulative Value Purchased and the Days since last purchase and the last day of the month.
i've tried this code
select c.Id AS CustomerId
,c.FirstName+' '+c.LastName as CustomerName
,DATENAME(MM,d.OrderDate) AS MonthofFirstPurchase
--,sum(d.TotalAmount) AS CummulativeValue
,d.OrderDate AS DateOfFirstPurchase
,Datediff(dd,o.OrderDate,getdate()) as DateSinceLastPurchase
from[dbo].[Customer]c inner join [dbo].[Order] b on b.CustomerId = c.Id
join (select max(Id) as OrderId, min(Id) as minOrder,[CustomerId] from [dbo].[Order] group by [CustomerId])conn on c.Id = conn.[CustomerId]
join [dbo].[Order]o on o.[Id] = conn.OrderId
join [dbo].[Order]d on d.[Id] = conn.minOrder
--join [dbo].[OrderItem]b on = conn.OrderId
but i keep getting errors i am a beginner at this
Please note that I did not execute the query.
If you do not want that column please try the below query. I did not execute the query though
;WITH CTE_Temp
AS
(
SELECT max(Id) AS OrderId
, min(Id) AS minOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, d.OrderDate) AS MonthofFirstPurchase
--,sum(d.TotalAmount) AS CummulativeValue
, d.OrderDate AS DateOfFirstPurchase
, Datediff(dd, o.OrderDate, getdate()) AS DateSinceLastPurchase
FROM [dbo].[Customer] c
INNER JOIN [dbo].[Order] b ON b.CustomerId = c.Id
INNER JOIN CTE_Temp conn ON c.Id = conn.[CustomerId]
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.OrderId
INNER JOIN [dbo].[Order] d ON d.[Id] = conn.minOrder
If you need the sum(d.TotalAmount) AS CummulativeValue. Just try the query
;WITH CTE_Temp
AS
(
SELECT max(Id) AS OrderId
, min(Id) AS minOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
),
CTE_TEMP1
AS
(
SELECT CTE_Temp.[CustomerId], sum(d.TotalAmount) TotalAmount AS CummulativeValue
FROM [dbo].[Order] d INNER JOIN CTE_Temp ON d.[Id] = CTE_Temp.minOrder
GROUP BY CTE_TEMP.[CustomerId]
)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, d.OrderDate) AS MonthofFirstPurchase
,CTE_TEMP1.TotalAmount AS CummulativeValue
, d.OrderDate AS DateOfFirstPurchase
, Datediff(dd, o.OrderDate, getdate()) AS DateSinceLastPurchase
FROM [dbo].[Customer] c
INNER JOIN [dbo].[Order] b ON b.CustomerId = c.Id
INNER JOIN CTE_Temp conn ON c.Id = conn.[CustomerId]
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.OrderId
INNER JOIN CTE_TEMP1 d ON d.CustomerId = c.id
I have modified the anser provided by Gopakumar and i came to the solution of the problem. The code below works perfectly well for its purpose
;WITH CTE_Temp
AS
(
SELECT max(Id) AS MaxOrder
, min(Id) AS MinOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
),
CTE_TEMP1 AS(SELECT CTE_TEMP.CustomerId,sum([UnitQuantity]) AS UnitsPurchasedForMonth,sum(TotalAmount) AS ValueForMonth
from [dbo].[OrderItem]p left outer join [dbo].[Order] e on p.Id = e.Id
INNER JOIN CTE_Temp ON e.[Id] = CTE_Temp.minOrder GROUP BY CTE_TEMP.CustomerId),
CTE_TEMP2 AS(SELECT e.CustomerId,sum([UnitQuantity]) AS CummulativeUnitsPurchased,sum(TotalAmount) AS CummulativeValue
from [dbo].[OrderItem]p inner join [dbo].[Order] e on p.Id = e.Id group by e.CustomerId)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, o.OrderDate) AS MonthofFirstPurchase
, o.OrderDate AS DateOfFirstPurchase
,d.ValueForMonth AS ValuePurchasedForMonth
,d.UnitsPurchasedForMonth
,e.CummulativeUnitsPurchased
,e.CummulativeValue
, Datediff(dd, a.OrderDate, getdate()) AS DateSinceLastPurchase
,EOMONTH(o.OrderDate) AS LastDayOfMonth
FROM [dbo].[Customer] c
INNER JOIN CTE_Temp conn ON c.Id = conn.CustomerId
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.MinOrder
INNER JOIN CTE_TEMP1 d ON d.CustomerId = c.id
INNER JOIN [dbo].[Order] a on a.Id = conn.MaxOrder
inner join CTE_TEMP2 e on c.Id = e.CustomerId
you can edit as you like to get your results
I am trying to get list of customers that have orders in January & February,but not in March
SELECT distinct C.CustID, FirstName + ', ' + LastName AS CustomerName, OrderDate
FROM Customers C JOIN Orders O ON
C.CustID = O.CustID
WHERE C.CustID in
(select CustID
from Customers
where month(OrderDate) >= 01)
and
C.CustID in
(select CustID
from Customers
where month(OrderDate) <= 02)
and
C.CustID IN
(select CustID
from Customers
where month(OrderDate) != 03);
Have a go with this:
SELECT C.CustID, C.FirstName + ', ' + C.LastName AS CustomerName, O1.OrderDate
FROM Customers C
INNER JOIN (
SELECT CustID FROM Orders WHERE month(OrderDate) IN (1,2)
) O1 ON C.CustID=O1.CustID
LEFT JOIN (
SELECT CustID FROM Orders WHERE month(OrderDate) IN (3)
) O2 ON C.CustID=O2.CustID
WHERE O2.CustID IS NULL
GROUP BY C.CustID, C.FirstName, C.LastName, O1.OrderDate
Find the customers that had orders in March and use a NOT IN operator instead of IN
SELECT distinct C.CustID, FirstName + ', ' + LastName AS CustomerName, OrderDate
FROM Customers C JOIN Orders O ON
C.CustID = O.CustID
WHERE C.CustID in
(select CustID
from ORders
where month(OrderDate) BETWEEN 1 AND 2)
AND C.CustID NOT IN
(select CustID
from ORders
where month(OrderDate) 03);
I also changed the first two where conditions into one so it's a smidge faster.
Also, as #Matthew pointed out, your CustID and OrderDate fields are probably on your Order table so it would work a bit better to use that in your subqueries.
SELECT C.CustID, C.FirstName + ', ' + C.LastName AS CustomerName, O1.OrderDate
FROM Customers C
LEFT OUTER JOIN
(SELECT CustID FROM Orders WHERE month(OrderDate) IN (3) ) O ON
O. CustID = C.CustID
WHERE month(C.OrderDate) IN (1,2)
AND O.CustID IS NULL
AdventureWorks2012 DB - I am trying to return top 1 or 2 emlpoyees from Finance dept and Engineer dept who have worked longest. I cant get my query to return both, only results from engineering show. Any suggestions?
SELECT TOP 2 EDH.StartDate, E.BusinessEntityID, D.Name, EDH.EndDate, DATEDIFF(hour,EDH.StartDate, GETDATE()) AS HoursWorked
FROM HumanResources.Employee E
INNER JOIN Person.Person PP ON E.BusinessEntityID = PP.BusinessEntityID
INNER JOIN HumanResources.EmployeeDepartmentHistory EDH ON E.BusinessEntityID = EDH.BusinessEntityID
INNER JOIN HumanResources.Department D ON D.DepartmentID = EDH.DepartmentID
WHERE (D.Name LIKE 'Finance' OR D.Name = 'Engineering')
AND EDH.EndDate IS NULL
GROUP BY D.Name, EDH.StartDate,E.BusinessEntityID,EDH.EndDate
ORDER BY EDH.StartDate ASC
Your problem is that the employees from Engineering happen to have started before the employees from Finance. The ORDER BY is affecting all of your records (both departments), and then the TOP 2 value is grabbing the two most recent employees, regardless of departments.
If you are trying to write a query that returns the first employee from each department, you're going to have to get a bit more complex. Here is an example that uses the ROW_NUMBER() function to order employees within each department by their start date, then filters those records to only return employees who are the first individuals in their department.
SELECT
StartDate,
BusinessEntityID,
Name,
EndDate,
HoursWorked
FROM
(
SELECT
EDH.StartDate,
E.BusinessEntityID,
D.Name,
EDH.EndDate,
DATEDIFF(hour,EDH.StartDate, GETDATE()) AS HoursWorked,
ROW_NUMBER() OVER (PARTITION BY D.Name ORDER BY EDH.StartDate) AS RowNumberWithinDepartment
FROM
HumanResources.Employee E
INNER JOIN
Person.Person PP ON E.BusinessEntityID = PP.BusinessEntityID
INNER JOIN
HumanResources.EmployeeDepartmentHistory EDH ON E.BusinessEntityID = EDH.BusinessEntityID
INNER JOIN
HumanResources.Department D ON D.DepartmentID = EDH.DepartmentID
WHERE
(D.Name LIKE 'Finance' OR D.Name = 'Engineering') AND
EDH.EndDate IS NULL
GROUP BY D.Name, EDH.StartDate,E.BusinessEntityID,EDH.EndDate
) x
WHERE RowNumberWithinDepartment = 1
ORDER BY StartDate ASC