【问题标题】:Query to randomly select from a table without repeating selection查询从表中随机选择而不重复选择
【发布时间】:2018-12-27 23:13:57
【问题描述】:

我有两个表:[employee][task],我想将每个 employeetask 表中的 5 个任务分配到跟踪表中。分配需要是随机的,并且每次选择都应该排除那些已经选择的任务。

【问题讨论】:

  • 选择查询 in random order 的行。只运行一次查询,并按从上到下的顺序使用该列表。

标签: sql-server


【解决方案1】:

我想我找到了一种优雅的方式来实现你想要的。唯一的问题是,如果您的任务少于 5 x 员工,则某些员工将根本没有分配任何任务。

WITH    Employee    AS (SELECT ROW_NUMBER() OVER(ORDER BY NewID()) AS ID, * FROM Employee),
        Task        AS (SELECT ROW_NUMBER() OVER(ORDER BY NewID()) AS ID, * FROM Task)
    SELECT *  
    FROM Employee
    LEFT JOIN Task
        ON Employee.ID = FLOOR((Task.ID-1)/5)+1

您可以将所需的结果插入到跟踪表中

根据您的评论,添加以确保任务按比例分配,如果任务> 5 x 员工可能会发生问题,系统将分配更多任务给一些员工:

WITH    Employee    AS (SELECT ROW_NUMBER() OVER(ORDER BY NewID()) AS ID, * FROM Employee),
            Task        AS (SELECT ROW_NUMBER() OVER(ORDER BY NewID()) AS ID, * FROM Task)
        SELECT *  
        FROM Employee
        LEFT JOIN Task
            ON Employee.ID = FLOOR((Task.ID-1) %
                   (SELECT COUNT(*) FROM Employee)
                  )+1

它使用 Modulus % 运算符来获得整数除法的其余部分,因此它为每个任务提供相关数字,当达到员工总数时,从 1 重新开始。

【讨论】:

  • 我想得很好,并且...也许您需要澄清您的要求,因为不确定是否可以将同一个任务分配给多个员工并且该过程会随着时间的推移而运行,所以,Tracking table 需要是增量的,所以,我的回复中应该添加一些额外的检查。
  • 当表很大时可能表现不佳,因为您为每个表中的每一行创建 2 个 NEWID()
  • 我无法想象一家公司拥有如此多的员工和任务会影响绩效......我在现有数据中看到了更多应该排除的问题......
  • 非常感谢!这很好用,除了每个人都应该有分配的任务,而这让一些人没有任务。你能解释一下这是做什么的吗?FLOOR((Task.ID-1)/5)+1 为什么是 -1 和 +1?
  • 我没有太多时间搜索正确的函数,但是,FLOOR 获取数字的整数部分,因此,对于 Task.ID = 1、2、3、4、5、6、7 , 8, 9,10, 11... 减去 1,除以 5 得到 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2... 所以,你需要搜索对于一个函数,它为您提供从 1 到最大员工数的数字,并且需要在该字段上链接。
【解决方案2】:

在这篇博文中:Return rows in random order 由 Robert Harvey 在评论中链接,您可以找到关于执行涉及ORDER BY NewID() 甚至ORDER BY Rand() 的查询的效率低下的讨论。

根据我的经验,完成您想要做的事情的最佳方法是引入一个新的索引列,比如RandomColumn,用随机数(使用Rand())填充一次,然后每次需要行随机选择一个随机数,比如R,然后选择如下:

...WHERE RandomColumn >= R ORDER BY RandomColumn.

【讨论】:

    猜你喜欢
    • 2020-02-19
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多