You could find a similar question here:
Using pivot table with column and row totals in sql server 2008
Using CUBE, a solution could be
WITH SalesLT_ProductCategory as (
SELECT * FROM (
VALUES
(1, 'Mountain Bikes'),
(2, 'Road Bikes'),
(3, 'Touring Bikes'),
(4, 'Brakes')
-- etc...
) AS a (ProductCategoryID, Name)
), SalesLT_Product AS (
SELECT * FROM (
VALUES
(1, 1, 'Red'),
(1, 1, 'Blue'),
(1, 1, 'Blue'),
(1, 1, 'Blue'),
(1, 2, 'Red'),
(1, 2, 'Red'),
(1, 2, 'Blue'),
(1, 2, 'Black'),
(1, 3, 'Black'),
(1, 3, 'Yellow'),
(1, 3, 'Grey'),
(1, 3, 'Grey'),
(1, 3, 'Grey'),
(1, 4, 'Red'),
(1, 4, 'Multi'),
(1, 4, 'Multi'),
(1, 4, 'Uncolored'),
(1, 4, 'Uncolored'),
(1, 4, 'Uncolored')
-- etc...
) AS a (ProductID, ProductCategoryID, Color)
), BaseData AS (
SELECT p.ProductID, pc.Name, ISNULL(p.Color, 'Uncolored') AS Color
FROM SalesLT_ProductCategory AS pc
INNER JOIN SalesLT_Product AS p ON pc.ProductCategoryID = p.ProductCategoryID
)
SELECT
Name,
COALESCE(Red, 0) AS Red,
COALESCE(Blue, 0) AS Blue,
COALESCE(Black, 0) AS Black,
COALESCE(Silver, 0) AS Silver,
COALESCE(Yellow, 0) AS Yellow,
COALESCE(Grey, 0) AS Grey,
COALESCE(Multi, 0) AS Multi,
COALESCE(Uncoloured, 0) AS Uncoloured,
Total
FROM (
SELECT
COALESCE(Name, 'Total') AS Name,
COALESCE(Color, 'Total') AS Color,
COUNT(*) AS Count
FROM BaseData
GROUP BY CUBE (Name, Color)
) AS t
PIVOT (
SUM(Count) FOR Color IN (
Red, Blue, Black, Silver, Yellow,
Grey, Multi, Uncoloured, Total
)
) AS p
ORDER BY CASE Name WHEN 'Total' THEN 1 ELSE 0 END, Name
Using CTE, an alternative solution could be
WITH SalesLT_ProductCategory as (
SELECT * FROM (
VALUES
(1, 'Mountain Bikes'),
(2, 'Road Bikes'),
(3, 'Touring Bikes'),
(4, 'Brakes')
-- etc...
) AS a (ProductCategoryID, Name)
), SalesLT_Product as (
SELECT * FROM (
VALUES
(1, 1, 'Red'),
(1, 1, 'Blue'),
(1, 1, 'Blue'),
(1, 1, 'Blue'),
(1, 2, 'Red'),
(1, 2, 'Red'),
(1, 2, 'Blue'),
(1, 2, 'Black'),
(1, 3, 'Black'),
(1, 3, 'Yellow'),
(1, 3, 'Grey'),
(1, 3, 'Grey'),
(1, 3, 'Grey'),
(1, 4, 'Red'),
(1, 4, 'Multi'),
(1, 4, 'Multi'),
(1, 4, 'Uncolored'),
(1, 4, 'Uncolored'),
(1, 4, 'Uncolored')
-- etc...
) AS a (ProductID, ProductCategoryID, Color)
), PivotData AS (
-- your query
SELECT *
FROM
(
SELECT p.ProductID, pc.Name, ISNULL(p.Color, 'Uncolored') AS Color
FROM SalesLT_ProductCategory AS pc
INNER JOIN SalesLT_Product AS p ON pc.ProductCategoryID = p.ProductCategoryID
)
AS PPC
PIVOT (COUNT(ProductID) FOR COLOR IN ([Red], [Blue], [Black], [Silver], [Yellow], [Grey], [Multi], [Uncolored]))
AS ColorPivotTable
), ColumnTotals AS (
-- column totals
SELECT
'Total' AS Name
, SUM(Red) AS Red
, SUM(Blue) AS Blue
, SUM(Black) AS Black
, SUM(Silver) AS Silver
, SUM(Yellow) AS Yellow
, SUM(Grey) AS Grey
, SUM(Multi) AS Multi
, SUM(Uncolored )AS Uncolored
FROM PivotData
), PivotDataWithRowTotals AS (
SELECT * FROM PivotData
UNION ALL
SELECT * FROM ColumnTotals
)
SELECT P.*
-- row totals
, P.Red + P.Blue + P.Black + P.Silver + P.Yellow + P.Grey + P.Multi + P.Uncolored as Total
FROM PivotDataWithRowTotals AS P