问题
Pretty new to SQL here - help would be much appreciated. I have a table with Region
, Month
, Member ID
, and Sales
(with multiple transactions per member). I just want to extract the top 2 members, based on sum of sales, per region, per month....so essentially:
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
Becomes:
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
Ultimately, there will be 10 regions, and I'd like to take the top 5 sales by member for each region, each month.
回答1:
You can do this with 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;
回答2:
If you are worried about ties (any you probably are as @Conrad Frix pointed out) you may prefer RANK() to ROW_NUMBER().
I'll borrow sample data, use CTEs for clarity, apply my preferred formatting, and provide a 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
回答3:
I see it's easier to use TOP statement
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
Results are:
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
来源:https://stackoverflow.com/questions/22770604/sql-server-2012-select-top-n-based-on-multiple-criteria