7

我的数据库有 3 个表,如下所示:

在此处输入图像描述

订单表有如下数据:

OrderID    OperatorID    GroupID        OrderDesc    Status    Cash    ...
--------------------------------------------------------------------------
      1             1          1      small order         1     100 
      2             1          1    another order         2       0 
      3             1          2      xxxxxxxxxxx         2    1000 
      5             2          2      yyyyyyyyyyy         2     150 
      9             5          1      xxxxxxxxxxx         1       0 
     10          NULL          2      xxxxxxxxxxx         1      10 
     11          NULL          3      xxxxxxxxxxx         1     120 

运算符表:

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

组表:

GroupID    Name
---------------
      1      G1
      2      G2
      3      X1

如您所见,John 有 3 个订单,Kate 1、Will 1、Jack 和 Sam 没有。

现在我想根据一些条件将操作员分配给订单:

  • 订单必须有现金>0
  • 订单必须有 status=1
  • 订单必须在第 1 组或第 2 组中
  • 操作员必须处于活动状态(活动 = 1)
  • 操作员必须在第 1 组或第 2 组中

这是我想要得到的结果:

OrderID    OperatorID    GroupID        OrderDesc    Status    Cash    ...
--------------------------------------------------------------------------
      1             1          1      small order         1     100       < change
      2             1          1    another order         2       0 
      3             2          2      xxxxxxxxxxx         2    1000       < change
      5             4          2      yyyyyyyyyyy         2     150       < change
      9             5          1      xxxxxxxxxxx         1       0 
     10             4          2      xxxxxxxxxxx         1      10       < change
     11          NULL          3      xxxxxxxxxxx         1     120 

我想改组订单并更新operatorID,以便每次调用此脚本时,我都会随机获得分配者operatorID,但是每个操作员的数量或订单数量都相同(接近相等,因为如果我有7个订单,则一个人将拥有3个并休息2)。

我可以使用NTILE将订单分配到组中,但我需要将 operatorID 分配给该组。

我认为我需要做这样的事情:

SELECT NTILE(2) OVER( order by orderID desc) as newID,* 
FROM
    orders(NOLOCK)

这将使我的订单表分成相等的部分。我需要知道的是操作符表的长度(将其作为参数添加到 NTILE),之后我可以将结果与操作符连接(使用row_number()

有更好的解决方案吗?

我的问题再次:如何将结果集平均分成组并使用另一个表数据更新该记录集?

编辑: 到目前为止,这是我的代码:http ://sqlfiddle.com/#!3/39849/25

编辑 2 我更新了我的问题并添加了更多条件。

我想根据一些条件将操作员分配给订单:

  • 订单必须有现金>0
  • 订单必须有 status=1
  • 订单必须在第 1 组或第 2 组中
  • 操作员必须处于活动状态(活动 = 1)
  • 操作员必须在第 1 组或第 2 组中

我将此查询构建为存储过程。
因此,第一步是在临时表中生成具有新分配的数据,并在第二步最终批准后根据该临时表更新主表。

我还有 2 个问题:

  1. 是先把所有的订单和所有满足条件的算子全选到临时表,然后再洗牌,还是在一个大查询中全部做?

  2. 我想将数组或组作为参数传递给我的过程。哪个选项最适合将数组传递给存储过程(SQL Server 2005)。

    我知道这被问了很多次,但我想知道是否最好创建一个单独的函数,将逗号分隔的字符串切割成表格(http://www.sommarskog.se/arrays-in-sql-2005.html ) 还是将所有内容都放在一个大胖程序中?:)


最终答案:可在http://sqlfiddle.com/#!3/afb48/2获得

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.cash>0 and 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

答案基于 Gordon 的 Linoff 答案。谢谢!

4

2 回答 2

1

我不确定您是否真的想要更新查询或选择查询。以下查询根据您的条件为每个订单返回一个新运算符:

/*
with orders as (select 1 as orderId, 'order1' as orderDesc, 1 as OperatorId),
     operators as (select 1 as operatorID, 'John' as name)
 */
select o.*, op.name 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) op
     ) o join
     (select op.*, ROW_NUMBER() over (order by newid()) as seqnum
      from Operators op
     ) op
     on o.randseqnum = op.seqnum order by orderid 

它基本上为连接的行分配了一个新的 ID。订单表获得一个介于 1 和随机分配的操作员数量之间的值。然后将其连接到运算符上的序列号。

如果您需要更新,那么您可以执行以下操作:

with toupdate as (<above query>)
update orders
    set operatorid = newoperatorid
    from toupdate
    where toupdate.orderid = orders.orderid

你的两个问题:

是先把所有的订单和所有满足条件的算子全选到临时表,然后再洗牌,还是在一个大查询中全部做?

临时表的用户是应用程序的性能和要求问题。如果数据正在快速更新,那么是的,使用临时表是一个很大的胜利。如果您在相同的数据上多次运行随机化,那么它可能是一个胜利,特别是如果表太大而无法放入内存中。否则,假设您将条件放在最里面的子查询中,一次性运行不可能有很大的性能提升。但是,如果性能是一个问题,您可以测试这两种方法。

我想将数组或组作为参数传递给我的过程。哪个选项最适合将数组传递给存储过程(SQL Server 2005)。

嗯,切换到具有表值参数的 2008。这是 Erland Sommarskog 撰写的关于该主题的高度参考文章:http: //www.sommarskog.se/arrays-in-sql-2005.html

于 2012-08-21T17:57:45.033 回答
0

抱歉——我认为你无法摆脱对记录集的计数......

DECLARE @myCount int
SELECT @myCount = Count(*) FROM Operators

SELECT
  a.OrderID, a.description, b.operatorName
FROM
  (
    SELECT NTILE(@myCount) OVER( ORDER BY NEWID()) AS newID, orderID, description
    FROM orders(NOLOCK)
  ) a
  INNER JOIN
  (
    SELECT NTILE(@myCount) OVER( ORDER BY NEWID()) AS newID, OperatorName, OperatorID
    FROM Operators
  ) b
  ON a.NewID = b.NewID
ORDER BY
   a.OrderID
于 2012-08-21T17:46:33.353 回答