ケースの分布はそれほど悪くありません。次のアプローチをお勧めします。
(1) お客様を 2 つのグループに分けます。. . 複数のケースと単一のケース。
(2) 複数のケースをラウンドロビン方式でケース ワーカーに割り当てます。
(3) 個々のケースをケース担当者に割り当てて、各ケース担当者のバランスをとります。
これは、特定のディストリビューション (主にシングルトン) で機能します。必ずしも汎用アルゴリズムではありません。
SQLは次のとおりです。
with multiples as (
select CustomerId, COUNT(*) CaseCnt,
ROW_NUMBER() over (partition by CustomerId order by CustomerId) % @NumHandlers as theHandler
from customers c
group by CustomerId
having COUNT(*) > 1
),
h as (
select theHandler, SUM(CaseCnt) as CaseCnt,
SUM(CaseCnt) - (NumCusts / @NumHandlers) as StillNeeded
from multiples cross join
(select COUNT(*) as NumCusts from customers c) const
group by theHandler
),
hsum as (
select h.*, SUM(StillNeeded) over (order by StillNeeded) as endnum,
SUM(StillNeeded) over (order by StillNeeded) - StillNeeded + 1 as startnum
from h
),
singles as (
select CustomerId, ROW_NUMBER() over (partition by CustomerId order by CustomerId) as seqnum
from Customers
group by CustomerId
having COUNT(*) = 1
),
singlesh as (
select singles.Customerid, h.theHandler
from singles join
hsum
on singles.seqnum between h.startnum and h.endnum
)
select *
from ((select CustomerId, theHandler
from multiples
) union all
(select CustomerId, theHandler
from singlesh
)
) t
SQL は、上記の説明にほとんど従っています。まず、複数のレコードをラウンドロビン方式でハンドラーにランダムに割り当てます。ハンドラーは、0 から @NumHandlers までの数値です。次に、「StillNeeded」ケースの数を計算して最大値を取得します。注: これは、ハンドラーの数が顧客数の正確な倍数であることを前提としています。修正する微調整により、クエリがより複雑に見えます。
次に、各ハンドラーに入力する必要がある数を計算します。重要なのは、これを累積合計として取得することです (これは SQL Server 2012 構文を使用します。以前のバージョンでは、相関サブクエリでこれを行います)。この情報は、シングルトンを各ハンドラーに割り当てるために使用されます。
最後のステップはunion
、マルチプルとシングルトンという 2 つのグループの顧客をまとめることです。