2016-06-08 14 views
0

Ich habe eine Tabelle der verfügbaren Teams teams, mit 24 verschiedenen Optionen.Zufällige Zuordnung, bis alle Optionen verwendet werden

Ich habe eine andere Tabelle entries, wobei jede Zeile eine Zuordnung von einem Team zu einem Benutzer ist.

Wenn ein Eintrag erstellt wird, wird ein zufälliges Team zugewiesen, das nicht ausgewählt wurde. Wenn jedoch alle Teams zugeteilt wurden (dies kann mehrfach vorkommen), sind nur Teams verfügbar, die in dieser Runde der Zuweisung noch nicht zugewiesen wurden.

Zum Beispiel, wenn meine Teams sind A, B, C und D:

  • Wenn ein Eintrag für A ist in entries, nur B, C und D sind verfügbar
  • Wenn A, B , C und D wurden ausgewählt, sie sind alle wieder verfügbar
  • Wenn A 3 Einträge hat, hat B 3 Einträge, C hat 2 Einträge und D hat 2 Einträge, nur C und D sind verfügbar, bis sie alle haben die gleiche Anzahl von Einträgen

Mein Code hierfür ist verworren:

//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; 

Es muss eine einfachere Methode, dies zu tun; Wie kann das gemacht werden?

Antwort

0

Im Folgenden finden Sie die Anzahl der Zuweisungen für jedes Team:

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

Dies gibt Ihnen die Mindestanzahl für jedes Team:

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

Um die Teams mit der Mindestzahl zu bekommen - jene verfügbar sein - aber diese beiden Abfragen zusammen zu einem:

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 
) 

Um auch diese Teams nicht y zu bekommen et enthalten in Einträge müssen wir auch das Team Tisch, auf dem alle Teams Entfernen derzeit nicht zur Auswahl:

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

Wegnehmen ') als tmin' funktioniert; Dies berücksichtigt jedoch keine Teams mit 0 Einträgen. Gibt es eine Möglichkeit, sie einzubeziehen? – Ben

0

ich keine Lösung gefunden haben, die nur in SQL arbeitet, aber ich angelegt habe die folgende query:

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 

Dies umfasst alle team Zeilen, die derzeit noch keine Einträge haben, und das Ergebnis ist eine Tabelle, die jedes Team in einer Spalte hat, und neben ihnen ist die Anzahl der Auswahlen.

Dann in PHP, ich nehme einfach den niedrigsten Wert von Auswahlen (dies wird die erste Reihe, wie ich von num_selected ASC bestellt haben) und verwenden Sie nur andere Zeilen mit diesem Wert als mögliche Optionen:

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

Idealerweise hätte ich jedoch eine Lösung, die ausschließlich in der SQL-Abfrage stattfindet!

Verwandte Themen