随机化返回结果 - 访问

时间:2018-01-18 14:12:35

标签: sql vba ms-access random

我需要将员工与我构建的小型Microsoft Access DB中的任务进行匹配。基本上,我列出了45个潜在任务,我有25名员工。我需要的是:

  1. 每位员工至少完成一项任务
  2. 没有员工超过两个
  3. 每次运行查询时都能随机化结果(因此同一个人不能始终如一地执行相同的任务)
  4. 我的表结构是: 员工 - 带字段:ID,名称 任务 - 带字段:ID,位置,任务组,任务

    我知道这是一个愚蠢的问题,但我真的在苦苦挣扎。我已经搜索了SO和谷歌的帮助,但都没有成功。

    我没有办法将员工与任务联系在一起,因为每个员工都能胜任每项任务,所以我打算:

    1. 来自员工的SELECT *
    2. SELECT * from Tasks
    3. 联盟
    4. COUNT(姓名)< = 2
    5. 但我不知道如何将这些结果随机化,以便人们随机匹配,每个人至少一次,不超过两次。

      感谢任何帮助或指导。谢谢。

1 个答案:

答案 0 :(得分:0)

考虑使用随机化选择集的聚合查询进行交叉连接。目前,在45 X 25处,这产生了1,125条记录的笛卡尔积,这是可管理的。

选择查询(另存为查询对象,假设任务具有自动编号字段)

SELECT cj.[Emp_Name], Max(cj.ID) As M_ID, Max(cj.Task) As M_Task
FROM
   (SELECT e.[Emp_Name], t.ID, t.Task
    FROM Employees e,
         Tasks t) cj
GROUP BY cj.[Emp_Name], Rnd(cj.ID)
ORDER BY cj.[Emp_Name], Rnd(cj.ID)

然而,这里的挑战是上面的查询随机化了每个25名员工的所有 45个任务的顺序,而您需要每个员工的前两个任务。不幸的是,MS Access没有像其他DBMS那样的行ID 来用于选择每位员工的前2名。并且我们不能在任务ID 员工上使用相关子查询,因为这将始终按其值返回最高的两个任务ID,而不是随机的前两个ID。

因此,要在Access中执行此操作,您需要在每次分配员工任务之前定期清除临时表,并使用自动编号通过相关子查询进行选择。

创建(运行一次,需要自动编号字段)

CREATE TABLE CrossJoinRandomPicks (
   ID AUTOINCREMENT PRIMARY KEY,
   Emp_Name TEXT(255),
   M_ID LONG,
   M_Task TEXT(255)
)

删除查询(定期运行)

DELETE FROM CrossJoinRandomPicks;

追加查询(定期投放)

INSERT INTO CrossJoinRandomPicks ([Emp_Name], [M_ID], [M_Task])
SELECT [Emp_Name], [M_ID], [M_Task] 
FROM mySavedCrossJoinQuery;

最终查询(为每位员工选择前两个随机任务)

SELECT c.name, c.M_Letter
FROM CrossJoinRandomPicks c
WHERE 
  (SELECT Count(*) FROM CrossJoinRandomPicks sub
   WHERE sub.name = c.name
     AND sub.ID <= c.ID) <= 2;