2016-06-08 2 views
0

У меня есть таблица доступных команд teams, с 24 различными вариантами.Случайное распределение до тех пор, пока не будут использованы все опции

У меня есть другая таблица entries, где каждая строка представляет собой выделение одной команды пользователю.

При создании записи выделяется случайная команда, которая не выбрана. Однако, если все команды выделены (это может произойти несколько раз), доступны только команды, еще не выделенные в этом раунде распределения.

Например, если мои команды A, B, C и D:

  • Если есть запись для А в entries, только B, C и D доступны
  • Если A, B , C и D были выбраны, это все доступно снова
  • IF 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; 

Там должна быть более простой способ для достижения этой цели; Как это может быть сделано?

ответ

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 
    ) 
) 
+0

Убирает '), как работает tmin'; однако это не учитывает команды с 0 записями. Есть ли способ включить их? – Ben

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-запросе!

Смежные вопросы