'How to turn distinct products into columns with the count as value
I have a table with customersID's and Products they have bought:
| CustomerId | Product |
|---|---|
| 3 | Apple |
| 3 | Orange |
| 3 | Banana |
| 7 | Orange |
| 7 | Orange |
| 7 | Banana |
| 9 | Apple |
| 9 | Apple |
| 9 | Banana |
I would like to create a column for each customer, with the amount of products they have bought of each distinct value:
| CustomerId | Apple | Orange | Banana |
|---|---|---|---|
| 3 | 1 | 1 | 1 |
| 7 | 0 | 2 | 1 |
| 9 | 2 | 0 | 1 |
For whatever reason, I'm having trouble finding a similar question online, which I suspect is due to my inability to formulate the question.
Solution 1:[1]
Today I learned about dynamic PIVOT queries - transform columns into rows. Combined with dynamic queries (queries whose content is not fully known until runtime), you can use PIVOT queries without knowing all the values in your column, by adding the values to the query during runtime.
Taking my question as an example:
Create and populate the first table in the question, which we will call Sales:
DROP TABLE IF EXISTS #Sales CREATE TABLE #Sales ( CustomerID INT, Product NVARCHAR(255) NOT NULL ); INSERT #Sales VALUES (3, N'Apple'), (3, N'Orange'), (3, N'Banana'), (7, N'Orange'), (7, N'Orange'), (7, N'Banana'), (9, N'Apple'), (9, N'Apple'), (9, N'Banana');Group by CustomerID and Product to count the amount bought of each product:
SELECT CustomerID , Product , COUNT(*) as Total_bought INTO #SalesSummed FROM #Sales GROUP BY CustomerID, ProductAdd each distinct Product to the pivot query:
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX); SET @columns = N''; SELECT @columns += N', p.' + QUOTENAME(Product) FROM (SELECT p.Product FROM #SalesSummed AS p GROUP BY p.Product) AS x; SET @sql = N' SELECT p.CustomerID, ' + STUFF(@columns, 1, 2, '') + ' INTO #SalesMatrix FROM ( SELECT p.CustomerID, p.Product, p.Total_bought FROM #SalesSummed AS p ) AS j PIVOT ( SUM(Total_bought) FOR Product IN (' + STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '') + ') ) AS p;'; PRINT @sql; EXEC sp_executesql @sql;
Step 3 yields the table SalesMatrix:
| CustomerID | Apple | Banana | Orange |
|---|---|---|---|
| 3 | 1 | 1 | 1 |
| 7 | NULL | 1 | 2 |
| 9 | 2 | 1 | NULL |
Which is exactly what we wanted (we can replace NULL with 0)!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
