2016-12-28 2 views
3

同じIDを持つ複数の行に行の値を配布する方法については、SQL Serverのヘルプが必要です。例示する、SQL Serverの複数の行に値を渡す

  • ID = ProductInventoryCode
  • 数量= QuantityInStock

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とブランチの分布はほぼ同じでなければなりません。

私は以下のようなものを手に入れましたが、多少混乱して経路を失いました。

私は現在、SQL Server 2008の

を使用してい

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 

我々はあるForDistributionQtyフィールドを配布するために使用下回っここでサンプル画面出力

enter image description here

は、上の結果は、145の支店でいます3130、私はこの問題のために正しくない分数(DistVal = 21.586)で終わっています、それは21のような整数でなければなりません、その21だけ21x145はちょうど3045です85台

答えて

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 
+0

私は分配されたqtyに等しい合計が終わったにもかかわらず、小数点で終わっていますが、私は整数だけが必要です。(私の元のreqsに対抗する)小数点を削除しながら分散されたqtyが等しくなるように制御します。 –

+0

@paulpoloあなたの個数はintフィールドなのですか? DistVal = cast(D.Qty as int)/C.Cnt –

+0

丸められた値が切り捨てられるため、qtyが欠落しています。小数点以下の桁数は21.56で、DistVal = cast(INTとしてのD.Qty)/C.Cntは21になります。したがって、それを合計配分数に掛け合わせると欠けています。 –

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 

あなたはintなると余りを保持するDistributedQtyが必要な場合は、私は@ジョンCappellettiのよりよい解決策を考えることはできません、凹凸の量もとまったくとしてではないかもしれないことを指摘あなたは望むかもしれない(例えば32で3を分配すると、11/11/10の分布ではなく12/10/10の分布になります)。

+1

個人的には、私が提示した精度が好きです。 –

関連する問題