2013-11-02 18 views
5

Ich möchte Top 3 Verkaufsprodukte für verschiedene Produktkategorie pro Tag herausziehen. Daten sieht wie folgt aus:SQL-select top 3 Werte pro Gruppe MIT BEDINGUNG

tag | product_name | product_category | order_count 
tag1 | product1  | category1  | 100 
tag1 | product2  | category2  | 80 
tag1 | product3  | category2  | 60 
tag1 | product4  | category3  | 50 
...... 

Ich weiß, wie oben 3 Verkauf von Produkten ziehen pro Tag mit ROW_NUMBER(), aber es wird wieder product1, product2, product3. Ich möchte nicht Produkt3, weil es zu der gleichen Kategorie wie Produkt2 gehört. Ich möchte stattdessen product4. Wie macht man das in SQL Server?

Antwort

4

Erste ROW_NUMBER entfernt doppelte Zeilen pro Tag und Produktkategorie, zweite ROW_NUMBER wählt die besten 3 verkaufenden Produkte pro Tag aus

;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 auf SQLFiddle

Als nächstes verwendet man eine abgeleitete Tabelle

;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 auf SQLFiddle

3

Sie können RANK() (oder ROW_NUMBER()) verwenden, solange Sie PARTITION BY verwenden. Dies in Kombination mit TOP() sollte gut funktionieren, vorausgesetzt, Sie SQL Server 2005+ verwenden:

with cte as (
    select tag, 
    product_name, 
    product_category, 
    order_count, 
    rank() over (partition by product_category 
       order by product_category, order_count desc) rnk 
    from yourtable 
) 
select top 3 tag, product_name, product_category, order_count 
from cte 
where rnk = 1 
order by order_count desc 

Dies wird produzieren folgende:

TAG  PRODUCT_NAME PRODUCT_CATEGORY ORDER_COUNT 
tag1 product1  category1   100 
tag1 product2  category2   80 
tag1 product4  category3   50 
0

würde ich mit einem tun es vorschlagen wählen nur

declare @t table (
    tag     varchar(10), 
    product_name  varchar(10), 
    product_category varchar(10), 
    order_count   int 
); 

insert into @t values 
('tag1', 'product1', 'category1', 100), 
('tag1', 'product2', 'category2', 80), 
('tag1', 'product3', 'category2', 60), 
('tag1', 'product4', 'category3', 50), 
('tag1', 'product5', 'category4', 40); 


select top 3 
    * 
from 
    @t 
order by 
    row_number() over(partition by product_category order by order_count desc), 
    order_count desc; 

SQL Fiddle