【问题标题】:SQL - Assign jobs to workers - Alternative to a loop?SQL - 将工作分配给工人 - 替代循环?
【发布时间】:2020-09-29 19:14:52
【问题描述】:

在 SQL Server 2019 中,我有一个未分配任务表,以及另一个可用于处理这些任务的工作人员表。我的要求是通过使用将执行任务的工作人员的ID 更新Tasks 表中的WorkerID 列,将工作人员平均分配给可用任务。

  • 每次运行 SQL 时,worker 的数量和任务的数量都可能不同。
  • 任一表的记录可能比另一表多。
  • 任务分配仅从 Workers 表中的第一个工作人员开始,并在任务全部分配完毕时结束。 (为了公平起见,没有随机分配工人。)
  • 任何一个表都可以有零条记录。

给定具有以下结构的表,我想知道如何在不使用循环的情况下进行这些分配。我怀疑这可以通过使用行号、排名或其他一些类似的 SQL Server 魔法来完成,但我无法弄清楚。谢谢!

任务表:

JobID    JobName           WorkerID
------------------------------------
23       Carry Groceries   NULL
1234     Drive             NULL
6543     Dig               NULL
234567   Walk              NULL
78       Clean Room        NULL
54       Cook Dinner       NULL
2        Move Logs         NULL
34       Cut Grass         NULL
99       Milk Chickens     NULL

工人表:

WorkerID   WorkerName
---------------------
67         Larry
42         Sue
10         Peter
45         Steve

Tasks 表的预期结果:

JobID    JobName           WorkerID
--------------------------------------
23       Carry Groceries   67
1234     Drive             42
6543     Dig               10
234567   Walk              45
78       Clean Room        67
54       Cook Dinner       42
2        Move Logs         10
34       Cut Grass         45
99       Milk Chickens     67

【问题讨论】:

    标签: sql sql-server sql-server-2019


    【解决方案1】:

    您可以使用窗口函数然后join 分配一个数字。 “循环”方法是:

    with toupdate as (
          select t.*, row_number() over (order by (select null)) as seqnum
          from tasks t
         )
    update toupdate
         from toupdate join
              (select w.*,
                      row_number() over (order by (select null)) as seqnum,
                      count(*) over () as cnt
               from workers w
              ) w
              on w.seqnum = ( (toupdate.seqnum - 1) % w.cnt) + 1;
    

    【讨论】:

    • 谢谢,戈登林诺夫!这很好用,虽然我发现第一个分配的工人是从工人中选择的第二个工人。由于它们无论如何都只是循环,这仍然符合规范,但为了未来维护者的理解,我在对其进行模数之前从 toupdate.seqnum 中减去 1,并且似乎已经对其进行了调整,以便分配的第一个工人是第一个选择的工人: on w.seqnum = ((toupdate.seqnum - 1) % w.cnt) + 1;
    • @user1876354 。 . .这似乎是合理的,你的建议是解决它的好方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多