I want to pull out top 3 selling products for different product category per tag. Data looks like this:
tag | product_name | product_category | order_count
tag1 | product1 | category1 | 100
tag1 | product2 | category2 | 80
tag1 | product3 | category2 | 60
tag1 | product4 | category3 | 50
......
I know how to pull out top 3 selling products per tag using ROW_NUMBER(), but it will return product1,product2,product3. I don't want product3 because it belongs to the same category as product2. I want product4 instead. How to do this in SQL server?
Typically, these are accomplished using the TOP or LIMIT clause. Problem is, Top N result sets are limited to the highest values in the table, without any grouping. The GROUP BY clause can help with that, but it is limited to the single top result for each group.
You can use a SELECT command with a GROUP BY clause to group all rows that have identical values in a specified column or combination of columns, into a single row.
First ROW_NUMBER removes duplicate rows per tag and product_category, second ROW_NUMBER selects top 3 selling products per tag
;WITH cte AS
(SELECT *, ROW_NUMBER() OVER(PARTITION BY tag, product_category ORDER BY order_count DESC) AS rn
FROM yourtable
), cte2 AS
(SELECT *, ROW_NUMBER() OVER(PARTITION BY tag ORDER BY order_count DESC) AS rn2
FROM cte
WHERE rn = 1
)
SELECT *
FROM cte2
WHERE rn2 <= 3
Demo on SQLFiddle
Next one uses a derived table
;WITH cte AS
(SELECT t2.tag, t2.product_name, t2.product_category, t2.order_count,
ROW_NUMBER() OVER(PARTITION BY t2.tag ORDER BY order_count DESC) AS rn
FROM (SELECT tag, product_category, MAX(order_count) AS maxCount
FROM yourtable
GROUP BY tag, product_category
) t1 JOIN yourtable t2 ON t1.tag = t2.tag
AND t1.product_category = t2.product_category
AND maxCount = order_count
)
SELECT *
FROM cte
WHERE rn <= 3
Demo on SQLFiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With