根据字段值均匀分配工作

时间:2011-09-06 23:45:20

标签: sql sql-server tsql sql-server-2008-r2

我有一个遗留系统,它使用一组机器人(自动化流程)来收集放置在“收件箱”中的作业。该工作分发到“发件箱”供其他机器人处理。每个作业都由表中的一行表示。每行都有一个代表该框的id。每个作业都有一个优先级,表示输出机器人执行工作的顺序。

今天收件箱1中的作业使用光标均匀分配到每个发件箱,使用光标再次处理收件箱2,依此类推,通过每个收件箱,不考虑优先级,因此一个发件箱可能具有许多高优先级,其他发件箱不会有任何高优先级的工作。

我希望找到一种方法来消除光标并根据发件箱中与收件箱具有相同优先级的作业分配作业。

    Start
id        box_name  priority
1         in_10         0
2         in_10         0
3         in_10         0
4         in_10         0
5         in_10         0
6         in_10         0
7         in_10         0
8         in_10         0
9         in_10         0
10        in_25         0
11        in_25         0
12        in_25         0
13        in_25         0
14        in_25         0
15        out_1         10
16        out_2         10
17        out_2         10
18        out_2         25

工作从“进入”转移到出去。优先级字段根据“输入”框的编号进行更新。

在上述情况中,总共有12个项目具有“10”优先级。项目是id:(1,2,3,4,5,6,7,8,9,15,16,17)。 12个项目,其中9个为“in”,3个为“out”,将分布在两个“out”框中。优先级10的输出框中的项目的目标计数是6.由于框1中当前有一个项目,我们将移动5个项目。方框2有2个项目,所以我们将移动4个项目。

对优先级25重复逻辑

AFTER
id        box_name  priority
1         out_1         10
2         out_1         10
3         out_1         10
4         out_1         10
5         out_1         10
6         out_2         10
7         out_2         10
8         out_2         10
9         out_2         10
10        out_1         25
11        out_1         25
12        out_1         25
13        out_2         25
14        out_2         25
15        out_1         10
16        out_2         10
17        out_2         10
18        out_2         25

以下是创建示例表的代码以及我开始使用的代码。我被困在如何编写更新语句。

declare @start table(id int identity(1,1), box_name char(10), priority int)
Insert @start (box_name, priority)
VALUES
('in',         10),
('in',         10),
('in',         10),
('in',         10),
('in',         10),
('in',         10),
('in',         10),
('in',         10),
('in',         10),
('in',         25),
('in',         25),
('in',         25),
('in',         25),
('in',         25),
('out_1',         10),
('out_2',         10),
('out_2',         10),
('out_2',         25)

--select * from @start
select distinct

[box_name], [priority]
,COUNT([box_name]) OVER (PARTITION BY [box_name],[priority] ) AS [count_source_by_priority]
,count([priority])OVER (PARTITION BY [priority] ) AS [Total_by_priority]
from @start

1 个答案:

答案 0 :(得分:0)

我能够在基于集合的时尚中实现这一目标。我在TSQL SQLServer2K8R2中使用了“ntile”。

declare @start table(id int identity(1,1), box_name char(10), priority int) 
Insert @start (box_name, priority) 
VALUES 
('in',         10), 
('in',         10), 
('in',         10), 
('in',         10), 
('in',         10), 
('in',         10), 
('in',         10), 
('in',         10), 
('in',         10), 
('in',         25), 
('in',         25), 
('in',         25), 
('in',         25), 
('in',         25), 
('out_1',         10), 
('out_2',         10), 
('out_2',         10), 
('out_2',         25) 

--select * from @start
--start of solution

--create a work table to hold the "out" box names
declare @out_box table (ob_id int identity(1,1), ob_name varchar(5))
--fill the work table
Insert @out_box
Select distinct box_name from @start where box_name != 'in'
--show the work table
select * from @out_box
--calculate the number of "out"boxes
declare @#ofOutBoxes int
select @#ofOutBoxes = MAX(ob_id) from @out_box
--show the calculated value
select @#ofOutBoxes
--reset all the work to "in" box
update @start set box_name = 'in' 
--create a table to hold the work with the newly associated "out" box
declare @start1 table(s1_id int identity(1,1), s1_s_id int, s1_box_name char(10), s1_priority int, s1_ntilevalue int, s1_targetRobot varchar(5)) 
Insert @start1 (s1_s_id,s1_box_name, s1_priority, s1_ntilevalue)
Select
id, box_name,priority,
NTILE(@#ofOutBoxes) OVER(PARTITION BY priority ORDER BY priority) AS 'ntilevalue' 
from @start 
--show the data
select * from @start1

---join the @start1 table and the @out_box table on the ntile value
UPDATE @Start1
SET s1_targetRobot = ob_name
from @start1 
inner join 
 @out_box 
 on s1_ntilevalue = ob_id

Select * from @Start1
--Use the joined table to update the @start table
UPDATE @Start
SET box_name = s1_targetRobot
FROM @Start
inner join 
 @Start1
 on id = s1_s_id

 Select * from @Start order by priority