我的数据库包含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没有。
现在我想基于某些条件将操作员分配给订单:
这是我想得到的结果:
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 我已经更新了我的问题,并添加了更多条件。
我想根据某些条件将操作员分配给订单:
我正在将此查询构建为存储过程 因此,第一步是生成具有新分配到临时表的数据,并在第二步中最终批准后根据该临时表更新主表。
我还有两个问题:
首先选择所有符合临时表条件的所有订单和所有运营商,然后进行改组或在一个大查询中完成所有操作会更好吗?
我想将数组或组作为参数传递给我的程序。哪个选项最好将数组传递给存储过程(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答案回答。谢谢!
答案 0 :(得分: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。
答案 1 :(得分: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