我需要有关SQL Server如何将行值分配给具有相同ID的多行的帮助。为了说明,
ForDistribution :
Id | Qty | TotalNoOfBranchesWithId
---+--------+-------------------------
1 | 40 | 2
2 | 33 | 3
3 | 21 | 2
将接收分发值
的表格Id | BranchCode | Qty | QtyFromForDistributionTable
-------------------------------------------------------
1 101 13 20
1 102 8 20
2 101 10 11
2 102 2 10
2 103 3 12
3 101 1 11
3 102 12 10
对于每个id和分支,分布应尽可能接近相等。
我得到了类似下面的东西,但有点迷茫和失去了道路。
with rs as
(
select
r.*, cume.cumequantity,
coalesce(s.shipped, 0) AS shipped
from
tmpForDistribution r
cross apply
(SELECT SUM([QuantityInStock]) AS cumequantity
FROM tmpForDistribution r2
WHERE r2.ProductInventoryCode = r.ProductInventoryCode) cume
left join
(SELECT ProductInventoryCode, COUNT(ProductInventoryCode) AS shipped
FROM tmpDistributed s
GROUP BY s.ProductInventoryCode) s ON r.ProductInventoryCode = s.ProductInventoryCode
)
select
rs.ProductInventoryCode, rs.cumequantity, rs.QuantityInStock,
***"how to distribute"***
from rs
我目前正在使用SQL Server 2008
这是一个示例屏幕输出
上面的结果是145分支,下面我们用来分配ForDistributionQty字段3130,我最后得到一个分数(DistVal = 21.586)这个问题不正确,它应该是一个整数,如然而,如果它只有21,那么21 x 145只是3045,这是85个单位。
答案 0 :(得分:3)
在这里,我们分发价值观,然后进行最后的调整"到具有最大数量(任意)的记录。但是在一天结束时,数学运算正常,分布式值也是正方形。
注意:不确定为什么在您的示例中为什么ID 2没有得到均匀分布
Declare @Table table (Id int,BranchCode int,Qty int)
Insert Into @Table values
(1, 101, 13),
(1, 102, 8),
(2, 101, 10),
(2, 102, 2),
(2, 103, 3),
(3, 101, 1),
(3, 102, 12)
Declare @Dist table (ID int,Qty int)
Insert Into @Dist values
(1,40),
(2,33),
(3,49)
;with cte0 as (
Select A.*
,ToDist = cast(D.Qty as int)
,DistVal = cast(D.Qty as int)/C.Cnt
,RN = Row_Number() over (Partition By A.ID Order By cast(D.Qty as int)/C.Cnt Desc,A.Qty Desc)
From @Table A
Join (Select ID,Cnt=count(*) from @Table Group By ID) C on A.ID=C.ID
Join @Dist D on A.ID=D.ID )
, cte1 as (
Select ID,AdjVal=Sum(DistVal)-max(ToDist) From cte0 Group By ID
)
Select A.ID
,A.BranchCode
,A.Qty
,DistVal = DistVal - case when A.RN<=abs(AdjVal) then 1*sign(AdjVal) else 0 end
From cte0 A
Join cte1 B on (A.ID=B.Id)
Order By 1,2
返回
ID BranchCode Qty DistVal
1 101 13 20
1 102 8 20
2 101 10 11
2 102 2 11
2 103 3 11
3 101 1 24
3 102 12 25
答案 1 :(得分:1)
如果你可以容忍十进制值,子查询似乎提供了一个更好的查询计划(在SQL 2014上测试,有一些合理的密钥,这可以避免表假脱机和一些额外的索引扫描):
Declare @Table table (Id int,BranchCode int,Qty int, primary key(id, branchcode))
Insert Into @Table values
(1, 101, 13),
(1, 102, 8),
(2, 101, 10),
(2, 102, 2),
(2, 103, 3),
(3, 101, 1),
(3, 102, 12)
Declare @Dist table (ID int primary key,Qty int)
Insert Into @Dist values
(1,40),
(2,33),
(3,21)
SELECT
t.id
,t.BranchCode
,t.Qty
,(d.Qty / CAST((SELECT COUNT(*) as cnt FROM @table t2 where t.id = t2.id) AS decimal(10,2))) as DistributedQty
FROM @Table t
INNER JOIN @Dist d
ON d.id = t.Id
输出:
Id BranchCode Qty DistributedQty
1 101 13 20.00000000000
1 102 82 20.00000000000
2 101 10 11.00000000000
2 102 21 11.00000000000
2 103 31 11.00000000000
3 101 11 10.50000000000
3 102 12 10.50000000000
如果您需要将DistributedQty设为int
并保留余数,那么我无法想到比@John Cappelletti更好的解决方案,并指出不均匀的数量可能不如确切地即使你可能希望(例如32分布为3将导致12/10/10分布而不是11/11/10分布)。