随机分配,直到使用所有选项

时间:2016-06-08 09:18:56

标签: php

我有一个可用的团队teams表,有24种不同的选项。

我有另一个表entries,其中每一行都是一个团队分配给用户。

创建条目时,会分配未被挑选的随机团队。但是,如果已经分配了所有队伍(这可能会多次发生),那么只有尚未在这轮分配中分配的队伍才可用。

例如,如果我的团队是A,B,C和D:

  • 如果entries中有A的条目,则只有B,C和D可用
  • 如果选择了A,B,C和D,则所有再次可用
  • 如果A有3个条目,B有3个条目,C有2个条目,D有2个条目,只有C和D可用,直到它们都具有相同的条目数

我的代码很复杂:

//Make array of teams
for($i=1;$i<=24;$i++) $team[$i] = 1;

//Get entries from database
$stmt = $dbh->prepare("SELECT `team` FROM `entries`");
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

//Create array of available teams
$numRows = $stmt->rowCount();
while($numRows >= 24) {
    for($i=1;$i<=24;$i++) {
        $team[$i] = $team[$i]+1;
    }
    $numRows = $numRows - 24;
}

//Remove entries for teams in array
foreach($rows as $row) $team[$row["team"]] = $team[$row["team"]]-1;
foreach($team as $i => $v) if($v > 0) $available[] = $i;

必须有一种更简单的方法来实现这一目标;怎么办呢?

2 个答案:

答案 0 :(得分:0)

以下为您提供每个团队的作业数量:

SELECT team, COUNT(*) FROM entries GROUP BY team;

这为您提供了任何团队的最低人数:

SELECT MIN(count) FROM (
  SELECT COUNT(*) as count FROM entries GROUP BY team
)

让团队获得最低数量 - 那些可用 - 但这两个查询合为一个:

SELECT teamcounts.team
FROM 
  (SELECT team, COUNT(*) as num FROM entries GROUP BY team) as teamcounts
WHERE 
  teamcounts.num = (
    SELECT MIN(num) FROM (
      SELECT COUNT(*) as num FROM entries GROUP BY team
    ) as tcounts
  )

要获得那些尚未包含在参赛作品中的球队,我们也必须使用球队表,删除目前无法选择的所有球队:

SELECT teams.name
FROM teams
WHERE teams.name NOT IN (
  SELECT teamcounts.team
  FROM 
    (SELECT team, COUNT(*) as num FROM entries GROUP BY team) as teamcounts
  WHERE 
    teamcounts.num != (
      SELECT MIN(num) FROM (
        SELECT COUNT(*) as num FROM entries GROUP BY team
      ) as tcounts
    )
)

答案 1 :(得分:0)

我还没有找到仅适用于SQL的解决方案,但是我已经创建了以下查询:

SELECT `id`, `num_selected` FROM
    (SELECT `id`, SUM(is_selected) AS `num_selected` FROM 
        (SELECT t.`id`, CASE WHEN e.`team` IS NULL THEN 0 ELSE 1 END AS is_selected FROM `entries` e RIGHT JOIN `teams` t ON t.`id` = e.`team`)
        AS `table1`
    GROUP BY `id`)
AS `table2` GROUP BY `id` ORDER BY `num_selected` ASC, `id` ASC

这包括所有没有条目的team行,结果是一个表,每个团队都在一列中,并且它们是选择的数量。

然后,在PHP中,我只选择最低的选择值(这将是第一行,因为我按num_selected ASC排序)并且只使用具有该值的其他行作为可能的选项:

$baseNum = $rows[0]["num_selected"];
foreach($rows as $row){
    if($row["num_selected"]===$baseNum) $availableTeams[] = $row["id"];
}

但是,理想情况下,我的解决方案只能在SQL查询中进行!