TSQL - 根据一个字段将行分成组

时间:2012-08-29 14:57:15

标签: sql tsql sql-server-2005

这是我之前问题的修改版:TSQL equally divide resultset to groups and update them

我的数据库包含2个表格,如下所示:

订单表包含如下数据:

OrderID    OperatorID    GroupID        OrderDesc    Status    Cash    ...
--------------------------------------------------------------------------
      1             1          1      small_order         1     300 
      2             1          1    another_order         1       0 
      3             1          2      xxxxxxxxxxx         2    1000 
      5             2          2      yyyyyyyyyyy         2     150 
      9             5          1      xxxxxxxxxxx         1      50 
     10          NULL          2      xxxxxxxxxxx         1     150 
     11          NULL          3      xxxxxxxxxxx         1     -50 
     12             4          1      xxxxxxxxxxx         1     200 

运营商表:

OperatorID    Name    GroupID    Active
---------------------------------------
      1       John          1         1
      2       Kate          1         1
      4       Jack          2         1
      5       Will          1         0
      6        Sam          3         0

我可以使用以下查询将我的记录集平均划分为相同的组:

SELECT o.*, op.operatorName AS NewOperator, op.operatorID AS NewOperatorId
FROM (SELECT o.*, (ROW_NUMBER() over (ORDER BY newid()) % numoperators) + 1 AS randseqnum
      FROM Orders o CROSS JOIN
     (SELECT COUNT(*) AS numoperators FROM operators WHERE operators.active=1) op
      WHERE o.status in (1,3)
     ) o JOIN
     (SELECT op.*, ROW_NUMBER() over (ORDER BY newid()) AS seqnum
      FROM Operators op WHERE op.active=1
     ) op
     ON o.randseqnum = op.seqnum ORDER BY o.orderID

演示于:http://sqlfiddle.com/#!3/ff47b/1

使用上面的脚本我可以将Orders划分为(几乎)相等的组,但是基于Number或Orders for Operator,但是我需要修改它以便它根据sum或Cash为Orders分配运算符订单。

例如:

如果我有6个Cash值的订单:300,0,50,150,-50,200,它们总和给出650.
我的脚本应该为3个运营商随机分配2个订单,其中Cash为订单的随机总和 我想要的是分配例如300,-50到operator1,200,0到第二和150,50到第三。
希望这听起来很清楚:)

以下是我希望获得的示例输出:

ORDERID  OPERATORID  GROUPID    DESCRIPTION  STATUS  CASH  NEWOPERATORID
------------------------------------------------------------------------
      1           1        1    small_order       1   300              2
      2           1        1  another_order       1     0              1
      9           5        1    xxxxxxxxxxx       1    50              4
     10      (null)        2    xxxxxxxxxxx       1   150              4
     11      (null)        3    xxxxxxxxxxx       1   -50              2
     12           4        1    xxxxxxxxxxx       1   200              1

我如何(如果可以的话)将操作员分配给我的订单,以使总和或Cash最接近平均值

1 个答案:

答案 0 :(得分:0)

如果我理解这一点,你可以通过订购最大的,然后是最小的,然后是下一个最大的,然后是下一个最小的,等等来获得你想要的结果。像这样:

ROW_NUMBER() over (order by CASE WHEN CashOrder % 2 = 1 then Cash else -Cash END) as splitCash

您使用

在查询中提供了较低的CashOrder
ROW_NUMBER() over (ORDER by CASH) as CashOrder

然后根据此拆分值指定每个运算符,即(对于三个运算符):

splitCash%3 +1