select 每个地区总订单量最高的客户,以及总订单量

select customer with the highest total orders per region, alongside both totals

我有一个 table 这样的:

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,什么是 select 每个地区最高订单客户的最佳方式,以及客户和地区的总数,即:

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

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

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

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

有 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;

关键特性是window聚合函数,所以我们只需要一个单个 CTE/子查询。

SQL Fiddle.

在一个select:

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