2016-12-28 4 views
3

동일한 ID를 가진 여러 행에 행 값을 배포하는 방법에 대한 SQL Server의 도움이 필요합니다. ,SQL Server에서 여러 행에 값을 할당하십시오.

  • 식 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와 분기마다 분포가 거의 같아야합니다.

아래와 같은 항목이 있지만 다소 혼란스럽고 길을 잃었습니다.

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 

나는 현재 샘플 화면 출력

enter image description here

우리가있는 ForDistributionQty 필드를 배포하는 데 사용 아래 상단 결과는 145 가지입니다 SQL 서버 여기에 2008

을 것 사용하고 있습니다 3130, 나는이 문제에 대해 정확하지 않은 분수 (DistVal = 21.586)로 끝나고있다. 그러나 그 21, 21x 145가 단지 3045 인 경우에는 21과 같은 정수가되어야한다. 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

비록 합계가 분배 된 수량만큼 끝났지 만, 소수만 필요합니다. (원래의 reqs에 반대하여) 균등하게 분배 된 수량이 필요하지 않습니다. 어떤 방법이 있습니까? 십진수를 제거하는 동안 분배 된 수량이 동일하게 유지되도록 제어합니다. –

+0

@paulpolo 귀하의 수량은 정수 필드입니까? 다른 경우 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 

당신이 DistributedQty이 고르지 수량이 정확히도 같이하지 않을 수 있음을 지적 int하고 내가 @ 존 CAPPELLETTI의보다 더 나은 솔루션을 생각할 수 없다 후 나머지를 유지해야하는 경우

너는 희망 할지도 모른다 (예를 들면. 32를 3으로 나누면 11/11/10 배포 대신 12/10/10 배포가됩니다).

+1

개인적으로, 내가 제시 한 정밀도를 선호합니다 (이탤릭은 재미 있습니다) +1 –