订单表具有如下数据:
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
如您所见,约翰有3个订单,凯特(Kate),威尔(Will),杰克(Jack)和山姆(Sam)没有。
现在,我想根据某些条件将操作员分配给订单:
这是我想要得到的结果:
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。
NTILE
我认为我需要做这样的事情:
SELECT NTILE(2) OVER( order by orderID desc) as newID,* FROM orders(NOLOCK)
这将使我的订单表分成相等的部分。我需要知道的是运算符表的长度(将其作为参数添加到NTILE中),之后我可以将结果与运算符合并(使用row_number())
row_number()
有更好的解决方案吗?
再次我的问题是: 如何将结果集平均划分为组,并使用另一个表数据更新该记录集?
编辑: 这是到目前为止我的代码:http : //sqlfiddle.com/#!3/39849/25
编辑2 我已经更新了我的问题,并添加了更多条件。
我想根据某些条件将操作员分配给订单:
我将这个查询构建为存储过程。 因此,第一步将是将具有新赋值的数据生成到临时表中,并在最终批准之后在第二步中基于该临时表更新主表。
我还有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
答案基于戈登的Linoff答案。谢谢!
我不确定您是否真的想要更新查询或选择查询。以下查询根据您的条件为每个订单返回一个新的运算符:
/* 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。