如何根据顺序计算每组值的差分和

时间:2017-01-22 08:09:35

标签: sql sql-server

我有一张发票表,其中包含客户,他们购买的产品以及销售额。

+----------+---------+-------+
| customer | product | sales |
+----------+---------+-------+
| bob      | apple   |    10 |
| john     | apple   |     8 |
| sarah    | apple   |     3 |
| bob      | pear    |    22 |
| glenn    | pear    |    13 |
| tim      | pear    |     8 |
| cody     | pear    |     4 |
+----------+---------+-------+

此表格将由

的查询生成
SELECT customer, product, SUM(sales) 
FROM Invoice 
GROUP BY customer, product 
ORDER BY product, SUM(sales) desc

是否可以编写一个查询来计算 - 每个产品 - 最高客户与其他客户之间的销售差异总和?例如,对于apple,值为9. (10 - 8) + (10 - 3) = 9。对于梨,值为41. (22 - 13) + (22 - 8) + (22-4) = 41

此新查询将返回

的结果
+---------+-----------+
| product | salesDiff |
+---------+-----------+
| apple   |         9 |
| pear    |        41 |
+---------+-----------+

对于只有1个客户的产品,我希望查询在销售差异中返回0。

4 个答案:

答案 0 :(得分:4)

首先确定每件产品的最大值。然后总结差异。

我已经包含了您的样本数据,并添加了一位购买橙子的客户来证明该要求的这一方面。

declare @t table (
    Customer varchar(10),
    Product varchar(10),
    Sales int
)
insert @t
select 'john', 'orange', 10 union all
select 'bob', 'apple', 10 union all
select 'john', 'apple', 8 union all
select 'sarah', 'apple', 3 union all
select 'bob', 'pear', 22 union all
select 'glenn', 'pear', 13 union all
select 'tim', 'pear', 8 union all
select 'cody', 'pear', 4

;with MaxSalesPerProduct as (
    select MAX(Sales) ms, Product
    from    @t t
    group by t.Product
)
select  t.Product, SUM(ms.ms - t.Sales)
from    @t t
        inner join MaxSalesPerProduct ms on
            ms.Product = t.Product
group by t.Product

请注意,没有对“顶级客户”进行特殊处理。是必要的,因为那里的差异取消为0。

<强>附录

虽然我的原始答案适用于您提供的示例数据,但它确实假设每个客户+产品组合只有一行。如果不是这种情况,那么您需要调整查询以将其考虑在内。

;with SalesPerCustomer as (
    select SUM(Sales) CustomerSales, t.Product, t.Customer
    from    @t t
    group by t.Product, t.Customer
), SaleStats as (
    select  spc.Product, MAX(spc.CustomerSales) MaxSales, COUNT(*) CustomerCount, SUM(spc.CustomerSales) TotalSales
    from    SalesPerCustomer spc
    group by spc.Product
)
select  *, MaxSales*CustomerCount - TotalSales as DiffSum
from    SaleStats

答案 1 :(得分:2)

使用另一个分组

包裹您的查询
SELECT product, count(customer)*max(sales) - SUM(sales) as diff
FROM (
    SELECT customer, product, SUM(sales) as sales
    FROM Invoice 
    GROUP BY customer, product 
) t
GROUP BY product 
ORDER BY SUM(sales) desc

答案 2 :(得分:1)

最简单的方法应该是在您查找销售总额的同一查询中找到最大销售额,然后通过汇总产品来总结差异。

试试这个:

select
    product, sum(max_sales - sales) salesDiff
from (
    SELECT customer, product, SUM(sales) sales, max(SUM(sales)) over (partition by product) max_sales
    FROM Invoice 
    GROUP BY customer, product
) t
group by product;

答案 3 :(得分:0)

不确定

    create table dbo.Customer_Prod
    (Customer varchar(32),
     Product varchar (32),
     Sales real
     )


insert into dbo.Customer_Prod values ('bob', 'apple', 10), ('john', 'apple', 8),('sarah', 'apple', 3),('bob', 'pear', 22),('glenn', 'pear', 13),('tim', 'pear', 8),('cody', 'pear', 4)


  with max_sales_Per_Product as (
  Select max(Sales) as Max_Sales, product
          from [AtlasDB].[dbo].[Customer_Prod] 
  Group by Product 
  )

  Select sum(B.Max_Sales - (A.sales)) AS Diff_Sales, A.Product 
  from [AtlasDB].[dbo].[Customer_Prod] A LEFT OUTER JOIN
  max_sales_Per_Product B on B.Product=A.Product
  group by A.Product

enter image description here