【发布时间】:2021-02-26 19:33:21
【问题描述】:
我一直在努力想出一个解决方案,该解决方案可以为一个区域内的客户创造 5 个平等的销售额。我尝试使用 while 循环和游标无济于事。我在其中定义了总销售额,然后将销售额除以 5,得出每个桶的销售额。
例如,如果总销售额为 100,000 美元,则存储桶大小将为 20,000 美元。该循环将从销售额最低到最高的客户开始填充存储桶 1,一旦分配到存储桶 2 的客户的总销售额超过 20,000 美元,将重复相同的过程以将剩余客户分配到存储桶 3-5 .
下面是一些生成示例数据的代码:
if object_id ('tempdb..#Customer') is not null
drop table #Customer;
CREATE TABLE #Customer(
CustomerID int
,Region varchar(30)
,Sales money
)
INSERT INTO #Customer Select '1', 'East', '0'
INSERT INTO #Customer Select '2', 'East', '20'
INSERT INTO #Customer Select '3', 'East', '40'
INSERT INTO #Customer Select '4', 'East', '60'
INSERT INTO #Customer Select '5', 'East', '80'
INSERT INTO #Customer Select '6', 'East', '100'
INSERT INTO #Customer Select '7', 'East', '120'
INSERT INTO #Customer Select '8', 'East', '140'
INSERT INTO #Customer Select '9', 'East', '160'
INSERT INTO #Customer Select '10', 'East', '180'
INSERT INTO #Customer Select '11', 'East', '200'
INSERT INTO #Customer Select '12', 'East', '220'
INSERT INTO #Customer Select '13', 'East', '240'
INSERT INTO #Customer Select '14', 'East', '260'
INSERT INTO #Customer Select '15', 'East', '280'
INSERT INTO #Customer Select '16', 'East', '300'
INSERT INTO #Customer Select '17', 'East', '320'
INSERT INTO #Customer Select '18', 'East', '340'
INSERT INTO #Customer Select '19', 'East', '360'
INSERT INTO #Customer Select '20', 'East', '380'
INSERT INTO #Customer Select '21', 'East', '400'
INSERT INTO #Customer Select '22', 'East', '420'
INSERT INTO #Customer Select '23', 'East', '440'
INSERT INTO #Customer Select '24', 'East', '460'
INSERT INTO #Customer Select '25', 'East', '480'
INSERT INTO #Customer Select '26', 'East', '500'
INSERT INTO #Customer Select '27', 'East', '520'
INSERT INTO #Customer Select '28', 'East', '540'
INSERT INTO #Customer Select '29', 'East', '560'
INSERT INTO #Customer Select '30', 'East', '580'
INSERT INTO #Customer Select '31', 'East', '600'
INSERT INTO #Customer Select '32', 'East', '620'
INSERT INTO #Customer Select '33', 'East', '640'
INSERT INTO #Customer Select '34', 'East', '660'
INSERT INTO #Customer Select '35', 'East', '680'
INSERT INTO #Customer Select '36', 'East', '700'
INSERT INTO #Customer Select '37', 'East', '720'
INSERT INTO #Customer Select '38', 'East', '740'
INSERT INTO #Customer Select '39', 'East', '760'
INSERT INTO #Customer Select '40', 'East', '780'
INSERT INTO #Customer Select '41', 'East', '800'
INSERT INTO #Customer Select '42', 'East', '820'
INSERT INTO #Customer Select '43', 'East', '840'
INSERT INTO #Customer Select '44', 'East', '860'
INSERT INTO #Customer Select '45', 'East', '880'
INSERT INTO #Customer Select '46', 'East', '900'
INSERT INTO #Customer Select '47', 'East', '920'
INSERT INTO #Customer Select '48', 'East', '940'
INSERT INTO #Customer Select '49', 'East', '960'
INSERT INTO #Customer Select '50', 'East', '980'
INSERT INTO #Customer Select '51', 'East', '1000'
INSERT INTO #Customer Select '52', 'East', '1020'
INSERT INTO #Customer Select '53', 'East', '1040'
INSERT INTO #Customer Select '54', 'East', '1060'
INSERT INTO #Customer Select '55', 'East', '1080'
INSERT INTO #Customer Select '56', 'East', '1100'
INSERT INTO #Customer Select '57', 'East', '1120'
INSERT INTO #Customer Select '58', 'East', '1140'
INSERT INTO #Customer Select '59', 'East', '1160'
INSERT INTO #Customer Select '60', 'East', '1180'
INSERT INTO #Customer Select '61', 'East', '1200'
INSERT INTO #Customer Select '62', 'East', '1220'
INSERT INTO #Customer Select '63', 'East', '1240'
INSERT INTO #Customer Select '64', 'East', '1260'
INSERT INTO #Customer Select '65', 'East', '1280'
INSERT INTO #Customer Select '66', 'East', '1300'
INSERT INTO #Customer Select '67', 'East', '1320'
INSERT INTO #Customer Select '68', 'East', '1340'
INSERT INTO #Customer Select '69', 'East', '1360'
INSERT INTO #Customer Select '70', 'East', '1380'
INSERT INTO #Customer Select '71', 'East', '1400'
INSERT INTO #Customer Select '72', 'East', '1420'
INSERT INTO #Customer Select '73', 'East', '1440'
INSERT INTO #Customer Select '74', 'East', '1460'
INSERT INTO #Customer Select '75', 'East', '1480'
INSERT INTO #Customer Select '76', 'East', '1500'
INSERT INTO #Customer Select '77', 'East', '1520'
INSERT INTO #Customer Select '78', 'East', '1540'
INSERT INTO #Customer Select '79', 'East', '1560'
INSERT INTO #Customer Select '80', 'East', '1580'
INSERT INTO #Customer Select '81', 'East', '1600'
INSERT INTO #Customer Select '82', 'East', '1620'
INSERT INTO #Customer Select '83', 'East', '1640'
INSERT INTO #Customer Select '84', 'East', '1660'
INSERT INTO #Customer Select '85', 'East', '1680'
INSERT INTO #Customer Select '86', 'East', '1700'
INSERT INTO #Customer Select '87', 'East', '1720'
INSERT INTO #Customer Select '88', 'East', '1740'
INSERT INTO #Customer Select '89', 'East', '1760'
INSERT INTO #Customer Select '90', 'East', '1780'
INSERT INTO #Customer Select '91', 'East', '1800'
INSERT INTO #Customer Select '92', 'East', '1820'
INSERT INTO #Customer Select '93', 'East', '1840'
INSERT INTO #Customer Select '94', 'East', '1860'
INSERT INTO #Customer Select '95', 'East', '1880'
INSERT INTO #Customer Select '96', 'East', '1900'
INSERT INTO #Customer Select '97', 'East', '1920'
INSERT INTO #Customer Select '98', 'East', '1940'
INSERT INTO #Customer Select '99', 'East', '1960'
INSERT INTO #Customer Select '100', 'East', '2980'
这是我目前使用的逻辑,它适用于一个区域,但当我尝试包含另一个区域时,逻辑会使用两个区域的总销售额来应用存储桶来计算存储桶。
if object_id ('tempdb..#rank') is not null
drop table #rank;
create table #rank (
customer_Id int
, region varchar(30)
, sales money
, sales_rank int
, bucket int
);
insert into #rank
select x.*
, row_number() over (order by x.sales desc) as sales_rank
, null as bucket
from #customer x;
declare @region_sales money, @bucket_amt money, @ctr int, @running_total money, @customer_id int, @sales money;
set @region_sales = (select sum(sales) from #customer);
set @bucket_amt = @region_sales / 5;
set @running_total = 0
set @ctr = 1
declare csr cursor forward_only for
select customer_id, sales from #rank order by sales_rank desc;
open csr
fetch next from csr into @customer_id, @sales
while @@FETCH_STATUS = 0
begin
if @running_total <= @bucket_amt
begin
set @running_total = @running_total + @sales;
update x set x.bucket = @ctr from #rank x where x.customer_id = @customer_id;
end
else
begin
set @running_total = 0
set @ctr = @ctr + 1
update x set x.bucket = @ctr from #rank x where x.customer_id = @customer_id;
end
fetch next from csr into @customer_id, @sales
end
close csr;
deallocate csr;
如何修改逻辑以分别为每个区域创建存储桶?
我对使用游标以外的任何其他方法持开放态度,因为这种方法在处理大量数据时可能会很慢。
使用上述相同的数据并复制为东部地区插入的记录并将重复的记录更改为西部地区(具有相同的客户和价值),此逻辑的最终结果将产生这些结果。
select Region, bucket, sum(sales) as Total_Sales from #rank
Group by Region, bucket
【问题讨论】:
标签: sql-server bucket