我的任务是获取一组客户并将他们分成两个相等的组,用于每个商店位置。请求的结果集将使每个商店位置的两组在客户数量上彼此相差 1% 以内,在订单数量上彼此相差在 1% 以内,在订购数量上彼此相差在 1% 以内。
下面是我想出的代码,它工作得很好,大多数时候它都能得到想要的结果,但有时(我认为由于组中的异常值)% 会比 1% 更远。
If OBJECT_ID('tempdb.dbo.#Orders') IS NOT NULL DROP TABLE #Orders
Select
StoreID
,CustomerID
,Sum(OrderID) as Orders
,Sum(OrderAmount) as AmountSold
Into #Orders
From CustomerOrders
Group by StoreID,CustomerID
IF OBJECT_ID('tempdb.dbo.#OrderRanking') IS NOT NULL DROP TABLE #OrderRanking
Select
O.*
,ROW_NUMBER() Over(Partition by StoreID Order by AmountSold, Orders) as Ranking
Into #OrderRanking
From #Orders as O
Select
R.StoreID
,Count(CustomerID) as CustomerCount
,Sum(R.Orders) as Orders
,Sum(R.AmountSold) as Amountsold
,Case When Ranking%2 = 0 Then 'A' Else 'B' End as 'Grouping'
From #OrderRanking as R
Group by
R.StoreID
,Case When Ranking%2 = 0 Then 'A' Else 'B' End
有没有更好的方法来拆分组以确保 1% 的方差?或者可能是一种循环遍历几个不同的拆分直到找到 1% 的方法?如果循环需要一个故障保险来防止无限循环,以防万一出现不可能的分割,比如在 x 循环之后,只需要最接近的分割。
我正在使用 SQL Server 2012 和 SSMS 2016。感谢您提供的任何帮助。
编辑:我曾尝试将代码转换为非公司特定的代码,但我弄乱了代码。我意识到这一点并调整了代码以显示真正受到追捧的内容。
Edit2:我自己取得了一些进展,并想更新问题。
所以我在这方面做了更多工作,每次运行代码时,我都能让它按随机顺序排序,并让它显示每个组的方差。现在我要添加的是一种循环 X 次并保留总体方差最低的方法。这个周末我可能会尝试更多的东西。但现在下面是我谈到的新代码。
If OBJECT_ID('tempdb.dbo.#Orders') IS NOT NULL DROP TABLE #Orders
Select
StoreID
,CustomerID
,Sum(OrderID) as Orders
,Sum(OrderAmount) as AmountSold
,Rand() as Random
Into #Orders
From CustomerOrders
Group by StoreID,CustomerID
IF OBJECT_ID('tempdb.dbo.#OrderRanking') IS NOT NULL DROP TABLE #OrderRanking
Select
O.*
,ROW_NUMBER() Over(Partition by StoreID Order by Random) as Ranking
Into #OrderRanking
From #Orders as O
If OBJECT_ID('tempdb.dbo.#Split') IS NOT NULL DROP TABLE #Split
Select
R.StoreID
,Count(CustomerID) as CustomerCount
,Sum(R.Orders) as Orders
,Sum(R.AmountSold) as Amountsold
,Case When Ranking%2 = 0 Then 'A' Else 'B' End as 'Grouping'
Into #Split
From #OrderRanking as R
Group by
R.StoreID
,Case When Ranking%2 = 0 Then 'A' Else 'B' End
Select
S.StoreID
,((Cast(Max(Case When S.[Grouping] = 'A' Then S.CustomerCount Else 0 End) as decimal(18,2))-Cast(Max(Case When S.[Grouping] = 'B' Then S.CustomerCount Else 0 End) as decimal(18,2)))
/ Cast(Max(Case When S.[Grouping] = 'B' Then S.CustomerCount Else 0 End) as decimal(18,2)))*100 as CustomerCountVar
,((Cast(Max(Case When S.[Grouping] = 'A' Then S.Orders Else 0 End) as decimal(18,2))-Cast(Max(Case When S.[Grouping] = 'B' Then S.Orders Else 0 End) as decimal(18,2)))
/ Cast(Max(Case When S.[Grouping] = 'B' Then S.Orders Else 0 End) as decimal(18,2)))*100 as OrderVar
,((Cast(Max(Case When S.[Grouping] = 'A' Then S.Amountsold Else 0 End) as decimal(18,2))-Cast(Max(Case When S.[Grouping] = 'B' Then S.Amountsold Else 0 End) as decimal(18,2)))
/ Cast(Max(Case When S.[Grouping] = 'B' Then S.Amountsold Else 0 End) as decimal(18,2)))*100 as AmountsoldVar
From #Split as S
Group by S.StoreID