选择每个地区总订单总数最高的客户以及总数

时间:2015-12-28 06:45:36

标签: sql sql-server greatest-n-per-group window-functions

我有一张这样的表:

SaleID    Region      Customer        OrderAmt
1         North       Keesha          10
2         West        Mary            10
3         North       Winston         10
4         North       John            10
5         North       Keesha          10
6         West        John            10
7         West        Mary            10
8         South       John            10

使用SQL Server 2012,选择每个地区最高订购客户的最佳方式是什么,以及客户和地区的总数,即:

Region    Customer    CustAmt   RegAmt
North     Keesha      20        40
West      Mary        20        30
South     John        10        10

虽然多个地区可能包含相同的名称,但我们希望CustAmt仅为每个地区内的名称总数,而不是跨地区(即最后一行,约翰在南部地区的总数)是10,而不是30)。

3 个答案:

答案 0 :(得分:2)

使用CTE:

WITH cte AS (
   SELECT Region, Customer
        , sum(OrderAmt) AS CustAmt
        , sum(sum(OrderAmt)) OVER (PARTITION BY Region) AS RegAmt
        , row_number()  OVER (PARTITION BY Region ORDER BY sum(OrderAmt) DESC) AS rn
   FROM   tbl
   GROUP  BY Region, Customer
   )
SELECT Region, Customer, CustAmt, RegAmt
FROM   cte
WHERE  rn = 1;

或者,与子查询相同:

SELECT Region, Customer, CustAmt, RegAmt
FROM  (
   SELECT Region, Customer
        , sum(OrderAmt) AS CustAmt
        , sum(sum(OrderAmt)) OVER (PARTITION BY Region) AS RegAmt
        , row_number()  OVER (PARTITION BY Region ORDER BY sum(OrderAmt) DESC) AS rn
   FROM   tbl
   GROUP  BY Region, Customer
   ) sub
WHERE  rn = 1;

关键功能是聚合上的窗口函数,因此我们只需要单个 CTE /子查询。

SQL Fiddle.

答案 1 :(得分:1)

在一个选择中:

select top 1 with ties
    Region   , 
    Customer ,
    CustAmt  =  sum(OrderAmt),
    RegAmt   =  sum(sum(OrderAmt)) over (partition by Region)   
from
    your_table
group by    
    Region, 
    Customer
order by 
    row_number() over(partition by Region order by sum(OrderAmt) desc);

<强> SQL Fiddle

答案 2 :(得分:0)

您可以使用多个CTE和窗口函数:

WITH Cte AS(
    SELECT *,
        CustAmt = SUM(OrderAmt) OVER(PARTITION BY Customer, Region),
        RegAmt  = SUM(OrderAmt) OVER(PARTITION BY Region)
    FROM Sales
),
CteFinal AS(
    SELECT *,
        rn = ROW_NUMBER() OVER(PARTITION BY Region ORDER BY CustAmt DESC)
    FROM Cte
)
SELECT
    Region, Customer, CustAmt, RegAmt
FROM CteFinal WHERE rn = 1

SQL Fiddle