Как уже говорили другие, вы можете использовать операторы PIVOT и UNPIVOT. К сожалению, одна из проблем как с PIVOT, так и с UNPIVOT заключается в том, что вам нужно знать значения, на которые вы будете поворачиваться, или использовать динамический SQL.
Похоже, в вашем случае вам нужно будет использовать динамический SQL. Чтобы это работало хорошо, вам нужно получить список продуктов, используемых в вашем запросе. Если бы вы использовали базу данных AdventureWorks, ваш код выглядел бы так:
USE AdventureWorks;
GO
DECLARE @columns NVARCHAR(MAX);
SELECT x.ProductName
INTO #products
FROM (SELECT p.[Name] AS ProductName
FROM Purchasing.Vendor AS v
INNER JOIN Purchasing.PurchaseOrderHeader AS poh ON v.VendorID = poh.VendorID
INNER JOIN Purchasing.PurchaseOrderDetail AS pod ON poh.PurchaseOrderID = pod.PurchaseOrderID
INNER JOIN Production.Product AS p ON pod.ProductID = p.ProductID
GROUP BY p.[Name]) AS x;
SELECT @columns = STUFF(
(SELECT ', ' + QUOTENAME(ProductName, '[') AS [text()]
FROM #products FOR XML PATH ('')
), 1, 1, '');
SELECT @columns;
Теперь, когда у вас есть столбцы, вы можете получить все, что вам нужно, с помощью динамического запроса:
DECLARE @sql NVARCHAR(MAX);
SET @sql = 'SELECT CustomerName, ' + @columns + '
FROM (
// your query goes here
) AS source
PIVOT (SUM(order_count) FOR product_name IN (' + @columns + ') AS p';
EXEC sp_executesql @sql
Конечно, если вам нужно убедиться, что вы получаете приличные значения, вам, возможно, придется продублировать логику, которую вы используете для построения @columns и создать переменную @coalesceColumns, которая будет содержать код COALESCE (col_name, 0) если вам нужно что-то подобное в вашем запросе.