2014-03-31 78 views
3

这里对SQL很新颖 - 帮助将不胜感激。我有一个RegionMonth,Member IDSales(每个成员有多个交易)的表格。我只是想提取顶部2个成员的基础上,销售的总和,每个地区,每月....所以基本上是:SQL Server 2012:根据多个条件选择Top n

Region Month  MemberID Sales 
----------------------------------------- 
    1  1/1/2013  A  $200 
    2  2/1/2013  B  $300 
    1  1/1/2013  A  $100 
    1  1/1/2013  B  $50 
    2  1/1/2013  D  $500 
    2  2/1/2013  C  $200 

变为:

Region Month Member ID Sales 
----------------------------------------- 
1 1/1/2013 A $300 
1 1/1/2013 B $50 
2 1/1/2013 D $500 
2 1/1/2013 B $200 

最终,将有10地区,我想每个月都会为每个地区的会员提供前五名的销售额。

+1

'我只是想提取前2名成员'如果第二名有一个平局,你想要发生什么?是否应该返回三排或是否有某种领带断裂?如果没有领带破坏者,你确定领带被任意破坏了吗? –

+0

您的示例不是特别有用,因为它只是删除2月份的条目。您是否想要按地区,每月销售额排名前2位的成员,还是您希望每个地区每月会员的前5位销售额? –

回答

2

你可以用row_number()做到这一点:

select region, month, MemberId, sales 
from (select region, month, MemberId, sum(sales) as sales 
      row_number() over (partition by region, month order by sum(sales) desc) as seqnum 
     from table t 
     group by region, month, MemberId 
    ) t 
where seqnum <= 2; 
+0

谢谢你的回应,戈登。我看到的一个问题是,我想只有前五名支出成员......我现在有一个行数为'1'的每一行: ;与T1作为 ( 选择 \t LOCATION, \t REGION, \t [YR_MO SERVICE], \t MEMBER_NBR, \t总和(浇铸从 \t [主表] 其中付费 (付费作为货币)) \t LOCATION = '12' 组由 \t位置, \t区域, \t [YR_MO SERVICE], \t MEMBER_NBR ) T2作为 ( 选择*, \t ROW_NUMBER()OVER(PARTITION BY地点,区域,[yr_mo服务],member_nbr ORDER BY付费说明)作为RN \t FROM \t \t T1 ) SELECT * 从 \t T2 其中 \t RN <= 5 – user3482508

+0

你在你的'分区by'列太多。我注意到我的答案在'partition by'中没有'MemberId'。 –

0

我看到它更容易使用TOP声明

create table Table1 
(
    Region int, 
    Month datetime, 
    [Member ID] char(1), 
    Sales float 
); 

insert into Table1 values (1, '1/1/2013', 'A', 200); 
insert into Table1 values (2, '2/1/2013', 'B', 300); 
insert into Table1 values (1, '1/1/2013', 'A', 100); 
insert into Table1 values (1, '1/1/2013', 'B', 50); 
insert into Table1 values (2, '1/1/2013', 'D', 500); 
insert into Table1 values (2, '2/1/2013', 'C', 200); 

select Top 5 Region, Month, [Member ID], sum(Sales) As [Total Sales] 
    from table1 
group by Region, Month, [Member ID] 
order by Region, Month, [Member ID], sum(Sales) desc 

结果是:

REGION MONTH    MEMBER ID TOTAL SALES 
     1 January, 01 2013 A 300 
     1 January, 01 2013 B 50 
     2 January, 01 2013 D 500 
     2 February, 01 2013 B 300 
     2 February, 01 2013 C 200 
+0

来自OP:“最终会有10个地区,我希望每个地区每个地区都有成员的前5名销售额。”这个查询没有达到OP的效果。 –

+0

有多少区域2,10或100无关紧要。 – yW0K5o

+0

这将只返回5个记录,期间。不是每个地区5。 –

2

如果你是担心 关于关系(任何你可能是@Conrad Frix指出的),你可能更喜欢RANK()到ROW_NUMBER()。

我会借用示例数据,使用CTE来清晰,应用我的首选格式,并提供SQLFiddle

CREATE TABLE MemberSales (
    Region INT 
,SalesMonth DATETIME 
,MemberID CHAR(1) 
,Sales FLOAT 
); 

INSERT INTO MemberSales VALUES (1, '1/1/2013', 'A', 200); 
INSERT INTO MemberSales VALUES (2, '2/1/2013', 'B', 300); 
INSERT INTO MemberSales VALUES (1, '1/1/2013', 'A', 100); 
INSERT INTO MemberSales VALUES (1, '1/1/2013', 'C', 300); 
INSERT INTO MemberSales VALUES (1, '1/1/2013', 'D', 100); 
INSERT INTO MemberSales VALUES (1, '1/1/2013', 'B', 50); 
INSERT INTO MemberSales VALUES (2, '1/1/2013', 'D', 500); 
INSERT INTO MemberSales VALUES (2, '2/1/2013', 'C', 200); 

;WITH SalesTotalByMember AS (
    SELECT Region 
     ,SalesMonth 
     ,MemberID 
     ,SUM(Sales) AS Sales 
    FROM MemberSales 
    GROUP BY Region 
      ,SalesMonth 
      ,MemberID 
), Ranked AS (
    SELECT Region 
     ,SalesMonth 
     ,MemberID 
     ,Sales 
     ,RANK() OVER (PARTITION BY Region, SalesMonth ORDER BY SALES DESC) rnk 
    FROM SalesTotalByMember 
) 
SELECT * 
    FROM Ranked 
WHERE rnk <= 2 
ORDER BY region 
     ,SalesMonth 
     ,rnk 
+0

这是一个很棒的答案。我有点震惊,这个问题没有更多的意见,也没有更多的选票。 – durron597