【问题标题】:Split total sum into categories based on range根据范围将总和拆分为类别
【发布时间】:2019-12-13 00:30:07
【问题描述】:

我正在尝试使用 MSSQL 将我的总销售额分成几类。

例如,10 月份的总销售额为 557.361。我需要将该总和分成三类,根据每个类别计算奖金价格,而其余部分溢出到下一个类别。

这可以使用 MSSQL 吗?

请参阅以下示例:

IF OBJECT_ID('tempdb..#sales') IS NOT NULL
    DROP TABLE #sales;

CREATE TABLE #sales
(
    year_month VARCHAR(10),
    total_sales INT
);


INSERT INTO #sales
(
    year_month,
    total_sales
)
VALUES
('2019-10-01', 557361),
('2019-11-01', 621801);

这将是预期的结果,请参见下图。

【问题讨论】:

  • group by month, category
  • 样本数据有助于我们思考OGloc
  • 一个选项可以是recursive CTE - 它是上限金额的一种变体:stackoverflow.com/a/52936314/5070879
  • @zip - 我添加了一些示例数据。这将是我必须使用的数据示例。
  • 太棒了@theOGloc,如果我们选择 10 月份,为什么我们没有达到 400000 的中等价格,而我们停在了 350000?

标签: sql sql-server


【解决方案1】:

在表格类别中,我将 Range 替换为展开 (max - min),这在查询中比其中带有 iphen 的字符串更有用。 我添加了一个分类订单来确定溢出的顺序,它称为 CategoyOrder 试试这个,请告诉我们:

/*************数据源**********************/

IF OBJECT_ID('tempdb..#sales') IS NOT NULL
    DROP TABLE #sales;

CREATE TABLE #sales
(
    year_month VARCHAR(10),
    total_sales INT
);


INSERT INTO #sales
(
    year_month,
    total_sales
)
VALUES
('2019-10-01', 557361),
('2019-11-01', 621801);

select * from #sales

IF OBJECT_ID('tempdb..#categories') IS NOT NULL
    DROP TABLE #categories;

CREATE TABLE #categories
(
    CategoryOrder int ,
    Category VARCHAR(10),
    price decimal(5,2),
    discount decimal(5,2),
    RangeSpread int ,
    CumulRangeSpread int 
);

INSERT INTO #categories
(
    CategoryOrder,
    Category,
    price,
    discount,
    RangeSpread,
    CumulRangeSpread  
)
VALUES
(1,'Small', 15, 0, 50000, 50000),
(2,'Medium', 13, 15, 350000, 400000),
(3,'Big', 11, 25, 400000, 800000);

select * from #categories

/************* END *****************/

/*************查询*******************/

;with cte as
(select c1.CategoryOrder, c1.Category, c1.price, c1.discount, c1.RangeSpread, isnull(c2.CumulRangeSpread, 0) as CumulRangeSpread from #categories c1 left join #categories c2 on c1.CategoryOrder -1 = c2.CategoryOrder) 

select c.CategoryOrder, c.Category, c.price, c.discount, total_sales, 
case when c.RangeSpread < total_sales - CumulRangeSpread  then c.RangeSpread else total_sales - CumulRangeSpread end as [CountIncategory], 
c.price*(case when c.RangeSpread < total_sales - CumulRangeSpread  then c.RangeSpread else total_sales - CumulRangeSpread end) as [Count*Price]
from cte c cross join #sales s order by total_sales, 2 desc

【讨论】:

    【解决方案2】:

    我认为这个解决方案不需要任何花哨的东西,只需要一些条件逻辑和算术。这是一个执行计算的脚本。为方便起见,您可以将其打包成一个函数。该函数可以接受@total_sales_base 作为参数。

    declare @total_sales_base int = 557361
    declare @total_sales decimal(10,3) = @total_sales_base / 1000.0
    
    drop table if exists #tmp
    create table #tmp (Category varchar(10), Total decimal(10,3))
    
    declare @sub decimal(10,3) = 0.0
    declare @bonus decimal(10,3) = 0.0
    
    set @sub = @total_sales - 50.0
    
    if (@sub > 0.0)
    begin
      set @bonus = 750.0
      set @total_sales = @total_sales - 50.0
    end
    else
    begin
      set @bonus = @total_sales * 15
      set @total_sales = 0.0
    end
    
    insert into #tmp select 'Small', @bonus
    
    set @sub = @total_sales - 350.0
    
    if (@sub > 0.0)
    begin
      set @bonus = 4550.0
      set @total_sales = @total_sales - 350.0
    end
    else
    begin
      set @bonus = @total_sales * 13
      set @total_sales = 0.0
    end
    
    insert into #tmp select 'Medium', @bonus
    
    set @bonus = @total_sales * 11
    
    insert into #tmp select 'Big', @bonus
    
    select * from #tmp
    

    输出:

    +----------+----------+
    | Category | Total    |
    +----------+----------+
    | Small    |  750.000 |
    | Medium   | 4550.000 |
    | Big      | 1730.971 |
    +----------+----------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-05
      • 2020-02-28
      相关资源
      最近更新 更多