patternsqlMinor
SQL query to get monthly sales per product, including products with no sales
Viewed 0 times
persqlwithqueryproductmonthlygetincludingsalesproducts
Problem
Let's say we have a Product table (product_id, product_name) and a Sales table (product_id, date, qty, amount).
What sql query would return the monthly sales per product, and include products with no sales?
(I'm using sql server if that makes any difference).
Clarification: I want a row for each possible month/product tuple. If there was no sales for a given month/product it should show zero qty/sales
What sql query would return the monthly sales per product, and include products with no sales?
(I'm using sql server if that makes any difference).
Clarification: I want a row for each possible month/product tuple. If there was no sales for a given month/product it should show zero qty/sales
Solution
See if this is what you're looking for (adjust as needed):
Note: The OP did not indicate they wanted a solution that takes the year into consideration, so my solution does not deal with the notion of a year when aggregating the data. If the month is January (regardless of year), the counts go in the January bucket.
UPDATE: To clarify a bit further, I want a row for each possible month/product tuple. If there was no sales for a given month/product it should show zero qty/sales
set nocount on
--Declare a months table (or use a Date Dimension table)
Declare @Months Table (MonthNumber tinyint, MonthName varchar(20))
insert into @Months (MonthNumber,MonthName) values
(1,'January'),
(2,'February'),
(3,'March'),
(4,'April'),
(5,'May'),
(6,'June'),
(7,'July'),
(8,'August'),
(9,'September'),
(10,'October'),
(11,'November'),
(12,'December')
--Declare a products table
Declare @Products table (Id int, ProductName Varchar(20))
insert into @Products (Id, ProductName)
values(1,'Widgets'),(2,'Thingamabob')
Declare @Sales table (product_id int, [date] Date, qty int, amount decimal(11,2))
insert into @Sales (product_id, [date], qty, amount)
values(1,'2017-01-01',1,100.00),(2,'2017-02-01',1,200.00),(2,'2017-06-01',2,300)
--Select Months and CROSS JOIN to Products, then
--LEFT JOIN to Sales. Use ISNULL to return zeros
--for months/products with no sales
SELECT m.MONTHNUMBER
,m.MonthName
,P.ProductName
,ISNULL(SUM(QTY), 0) AS QTY
,ISNULL(SUM(AMOUNT), 0) AS AMOUNT
FROM @Months m
CROSS JOIN @Products p
LEFT JOIN @Sales s ON DatePart(MONTH, [date]) = M.MonthNumber
AND S.product_id = P.ID
GROUP BY m.MonthNumber
,m.MonthName
,P.ProductName
ORDER BY M.MonthNumber
,m.MonthName
,P.ProductName| MONTHNUMBER | MonthName | ProductName | QTY | AMOUNT |
|-------------|-----------|-------------|-----|--------|
| 1 | January | Thingamabob | 0 | 0.00 |
| 1 | January | Widgets | 1 | 100.00 |
| 2 | February | Thingamabob | 1 | 200.00 |
| 2 | February | Widgets | 0 | 0.00 |
| 3 | March | Thingamabob | 0 | 0.00 |
| 3 | March | Widgets | 0 | 0.00 |
| 4 | April | Thingamabob | 0 | 0.00 |
| 4 | April | Widgets | 0 | 0.00 |
| 5 | May | Thingamabob | 0 | 0.00 |
| 5 | May | Widgets | 0 | 0.00 |
| 6 | June | Thingamabob | 2 | 300.00 |
| 6 | June | Widgets | 0 | 0.00 |
| 7 | July | Thingamabob | 0 | 0.00 |
| 7 | July | Widgets | 0 | 0.00 |
| 8 | August | Thingamabob | 0 | 0.00 |
| 8 | August | Widgets | 0 | 0.00 |
| 9 | September | Thingamabob | 0 | 0.00 |
| 9 | September | Widgets | 0 | 0.00 |
| 10 | October | Thingamabob | 0 | 0.00 |
| 10 | October | Widgets | 0 | 0.00 |
| 11 | November | Thingamabob | 0 | 0.00 |
| 11 | November | Widgets | 0 | 0.00 |
| 12 | December | Thingamabob | 0 | 0.00 |
| 12 | December | Widgets | 0 | 0.00 |Note: The OP did not indicate they wanted a solution that takes the year into consideration, so my solution does not deal with the notion of a year when aggregating the data. If the month is January (regardless of year), the counts go in the January bucket.
UPDATE: To clarify a bit further, I want a row for each possible month/product tuple. If there was no sales for a given month/product it should show zero qty/sales
Code Snippets
set nocount on
--Declare a months table (or use a Date Dimension table)
Declare @Months Table (MonthNumber tinyint, MonthName varchar(20))
insert into @Months (MonthNumber,MonthName) values
(1,'January'),
(2,'February'),
(3,'March'),
(4,'April'),
(5,'May'),
(6,'June'),
(7,'July'),
(8,'August'),
(9,'September'),
(10,'October'),
(11,'November'),
(12,'December')
--Declare a products table
Declare @Products table (Id int, ProductName Varchar(20))
insert into @Products (Id, ProductName)
values(1,'Widgets'),(2,'Thingamabob')
Declare @Sales table (product_id int, [date] Date, qty int, amount decimal(11,2))
insert into @Sales (product_id, [date], qty, amount)
values(1,'2017-01-01',1,100.00),(2,'2017-02-01',1,200.00),(2,'2017-06-01',2,300)
--Select Months and CROSS JOIN to Products, then
--LEFT JOIN to Sales. Use ISNULL to return zeros
--for months/products with no sales
SELECT m.MONTHNUMBER
,m.MonthName
,P.ProductName
,ISNULL(SUM(QTY), 0) AS QTY
,ISNULL(SUM(AMOUNT), 0) AS AMOUNT
FROM @Months m
CROSS JOIN @Products p
LEFT JOIN @Sales s ON DatePart(MONTH, [date]) = M.MonthNumber
AND S.product_id = P.ID
GROUP BY m.MonthNumber
,m.MonthName
,P.ProductName
ORDER BY M.MonthNumber
,m.MonthName
,P.ProductName| MONTHNUMBER | MonthName | ProductName | QTY | AMOUNT |
|-------------|-----------|-------------|-----|--------|
| 1 | January | Thingamabob | 0 | 0.00 |
| 1 | January | Widgets | 1 | 100.00 |
| 2 | February | Thingamabob | 1 | 200.00 |
| 2 | February | Widgets | 0 | 0.00 |
| 3 | March | Thingamabob | 0 | 0.00 |
| 3 | March | Widgets | 0 | 0.00 |
| 4 | April | Thingamabob | 0 | 0.00 |
| 4 | April | Widgets | 0 | 0.00 |
| 5 | May | Thingamabob | 0 | 0.00 |
| 5 | May | Widgets | 0 | 0.00 |
| 6 | June | Thingamabob | 2 | 300.00 |
| 6 | June | Widgets | 0 | 0.00 |
| 7 | July | Thingamabob | 0 | 0.00 |
| 7 | July | Widgets | 0 | 0.00 |
| 8 | August | Thingamabob | 0 | 0.00 |
| 8 | August | Widgets | 0 | 0.00 |
| 9 | September | Thingamabob | 0 | 0.00 |
| 9 | September | Widgets | 0 | 0.00 |
| 10 | October | Thingamabob | 0 | 0.00 |
| 10 | October | Widgets | 0 | 0.00 |
| 11 | November | Thingamabob | 0 | 0.00 |
| 11 | November | Widgets | 0 | 0.00 |
| 12 | December | Thingamabob | 0 | 0.00 |
| 12 | December | Widgets | 0 | 0.00 |Context
StackExchange Database Administrators Q#188719, answer score: 5
Revisions (0)
No revisions yet.