Original Problem
Using AdventureWorks2008R2
, write a query to return the salesperson id, number of unique products sold, highest order value, total sales amount, and top 3 orders for each salesperson.
Use TotalDue
in SalesOrderHeader
when calculating the highest order value and total sales amount. The top 3 orders have the 3 highest total order quantities. If there is a tie, the tie must be retrieved. Exclude orders which don't have a salesperson for this query. Return only the salespersons whose total sales were
greater than $9800000.
Return the order value and total sales as int. Sort the returned data by SalesPersonID
. The returned data should have a format as displayed below. Use the sample format for formatting purposes only.
Result
SalesPersonID | TotalUniqueProducts | OrderValue | TotalSales | Orders |
---|---|---|---|---|
275 | 242 | 165029 | 10475367 | 47395, 46666, 46662 |
276 | 244 | 145742 | 11695019 | 51721, 47355, 57046 |
277 | 246 | 132728 | 11342386 | 51748, 53560, 47027 |
Code:
WITH SalesData AS
(
SELECT
soh.SalesPersonID,
soh.SalesOrderID,
sod.ProductID,
soh.TotalDue
FROM
Sales.SalesOrderHeader soh
JOIN
Sales.SalesOrderDetail sod ON sod.SalesOrderID = soh.SalesOrderID
WHERE
soh.SalesPersonID IS NOT NULL
),
RankedSalesData AS
(
SELECT
SalesPersonID,
SalesOrderID,
TotalDue,
ROW_NUMBER() OVER (PARTITION BY SalesPersonID ORDER BY TotalDue DESC) AS SalesRank
FROM
(SELECT DISTINCT SalesPersonID, SalesOrderID, TotalDue FROM SalesData) AS UniqueSalesData
),
SalesSummary AS
(
SELECT
SalesPersonID,
COUNT(DISTINCT ProductID) AS UniqueProductsSold,
Cast(MAX(TotalDue)as int) AS HighestOrderValue,
Cast(SUM(TotalDue) as int) AS TotalSalesAmount
FROM
SalesData
GROUP BY
SalesPersonID
)
SELECT
SS.SalesPersonID,
SS.UniqueProductsSold,
SS.HighestOrderValue,
SS.TotalSalesAmount,
STUFF((SELECT ',' + CAST(R.SalesOrderID AS VARCHAR)
FROM RankedSalesData R
WHERE R.SalesPersonID = SS.SalesPersonID AND R.SalesRank <=3
FOR XML PATH('')), 1, 1, '') AS Top3Orders
FROM
SalesSummary SS
WHERE
SS.TotalSalesAmount > 9800000
ORDER BY
SS.SalesPersonID;
My result:
Salesperson ID | Unique Product sold | HighestOrdervalue | Totalsalesamount | Top3 Orders |
---|---|---|---|---|
274 | 216 | 126852 | 45434066 | 51830,57136,53465 |
275 | 242 | 165029 | 327853784 | 47395,53621,50289 |
276 | 244 | 145742 | 381125561 | 47355,51822,57186 |
277 | 246 | 132728 | 347868655 | 46660,43884,44528 |
278 | 234 | 96937 | 102841549 | 44534,43890,58932 |
279 | 245 | 142312 | 201612866 | 44518,43875,47455 |
If you see the TotalSales Amount
, it is multiplying multiple orders into the final amount and not matching the answer. I don't know where I am doing it wrong. I already tried to debug it with ChatGPT. So, Please save your answer from that. If you can explain in detail where I go wrong, It will be greatly appreciated in my academic career. I thank you ahead.
You will have to change the object names in this. This code assumes the existence of two tables:
CREATE TABLE InvoiceItems (InvoiceItemID BIGINT IDENTITY(1,1) NOT NULL, InvoiceID BIGINT NOT NULL, Sequence INT NULL, Quantity INT NULL, Cost DECIMAL(7, 2) NULL, Price DECIMAL(7, 2) NULL, ProductID BIGINT NULL)
CREATE TABLE Invoices (InvoiceID BIGINT IDENTITY(1,1) NOT NULL, InvoiceDateTimeUTC DATETIME2(7) NULL, CustomerID BIGINT NULL, EmployeeID BIGINT NULL, StoreID INT NULL)
(These are part of a script I maintain which generates completely randomized sales data, with proper constraints and all sorts of fun)
The code should provide an example of a way to produce the results you're looking for.
USE RandomSales;
;WITH Sales AS (
SELECT i.InvoiceID, i.InvoiceDateTimeUTC, i.CustomerID, i.EmployeeID, i.StoreID, ii.InvoiceItemID, ii.Sequence, ii.Quantity, ii.Cost, ii.Price, ii.ProductID,
ii.Price*ii.Quantity AS ItemTotal,
ii.Cost*ii.Quantity AS ItemValue,
SUM(ii.Price*ii.Quantity) OVER (PARTITION BY i.InvoiceID ORDER BY @@SPID) AS InvoiceTotal,
SUM(ii.Cost*ii.Quantity) OVER (PARTITION BY i.InvoiceID ORDER BY @@SPID) AS InvoiceValue,
SUM(ii.Quantity) OVER (PARTITION BY i.InvoiceID ORDER BY @@SPID) AS QuantityTotal
FROM dbo.Invoices i
INNER JOIN dbo.InvoiceItems ii
ON ii.InvoiceID = i.InvoiceID
), QtyRankByEmployee AS (
SELECT EmployeeID, STRING_AGG(InvoiceId,', ') AS Invoices
FROM (
SELECT Sales.EmployeeID, Sales.InvoiceID, MAX(Sales.QuantityTotal) AS Qty, RANK() OVER (PARTITION BY Sales.EmployeeID ORDER BY MAX(Sales.QuantityTotal) DESC) AS QtyRank
FROM Sales
GROUP BY Sales.EmployeeID, Sales.InvoiceID
) a
WHERE a.QtyRank <= 3
GROUP BY a.EmployeeID
), EmployeeTotal AS (
SELECT EmployeeID, COUNT(DISTINCT ProductID) AS TotalUniqueProducts, SUM(InvoiceValue) AS TotalValue, SUM(InvoiceTotal) AS TotalSales
FROM Sales s
GROUP BY EmployeeID
)
SELECT e.EmployeeID, e.TotalUniqueProducts, e.TotalValue, e.TotalSales, q.Invoices
FROM EmployeeTotal e
LEFT OUTER JOIN QtyRankByEmployee q
ON e.EmployeeID = q.EmployeeID
EmployeeID | TotalUniqueProducts | TotalValue | TotalSales | Invoices |
---|---|---|---|---|
1 | 31 | 6527.00 | 9082.20 | 8, 17, 5, 9 |
2 | 31 | 14397.00 | 19951.10 | 29, 37, 50 |
3 | 31 | 17304.00 | 24658.40 | 80, 86, 90 |
4 | 31 | 9992.50 | 14061.20 | 147, 152, 137 |
5 | 30 | 9608.00 | 13637.30 | 176, 201, 168 |
6 | 31 | 13396.00 | 18578.20 | 261, 257, 219 |
7 | 31 | 13850.50 | 19199.30 | 303, 306, 279, 285, 287 |
8 | 31 | 12420.00 | 17395.10 | 323, 327, 353, 368 |
9 | 31 | 16013.00 | 22568.50 | 409, 383, 382, 394, 370 |
10 | 31 | 12976.50 | 18055.10 | 423, 432, 434, 435 |
11 | 31 | 11641.00 | 16178.70 | 505, 496, 497, 486 |
12 | 31 | 10915.50 | 15387.40 | 529, 542, 544 |
13 | 31 | 14112.00 | 19650.70 | 556, 591, 587 |
14 | 31 | 15196.00 | 21490.90 | 617, 643, 644, 619, 628, 611 |
15 | 31 | 16220.50 | 22603.80 | 667, 652, 656, 686, 688 |
16 | 31 | 13231.50 | 18714.90 | 731, 727, 738, 742, 751, 711 |
17 | 31 | 11027.50 | 15881.30 | 754, 785, 788 |
... | ... | ... | ... | ... |