PHP/SQL - hämta och sortera anställda

Permalänk

PHP/SQL - hämta och sortera anställda

Jag har ett problem. Jag har en tabell där jag sätter anställda till olika avdelningar som heter crosstable.
Jag vill få ut den/dom som har minst antal rader (minst kompabilitet mot en avdelning) och det är inga problem.
Problemet uppstår när det är fler än 1 som har samma antal, då visar min hämtning bara den som ligger först i databasen.
Hur bör jag gå tillväga för att få ut alla 'person_id' som har lägst rader i min tabell?

Sedan vill jag slumpa fram en av dom här som jag placerar i en avdelning som dom är kompatibla mot.

<?php include "conn.php"; include "functions.php"; countCompatible($mysqli); $result = mysqli_query($mysqli,"SELECT *, COUNT(*) as antal FROM crosstable GROUP BY person_id;"); while($row = mysqli_fetch_array($result)) { echo "<b>Person: ".$row['person_id']." Antal: ".$row['antal']."</b><br>"; $array[$row['person_id']] = $row['antal']; } $lowestSections = min($array); $test = array_search('1', $array); //Här vill jag få ut "Den/dom här personerna har lägst antal kompatibla avdelningar" echo "<br>Den här personen ".$test." har lägst antal kompatibla avdelningar"; ?> [/php]

Permalänk
Hedersmedlem
Skrivet av RobinJacobsson:

Jag har ett problem. Jag har en tabell där jag sätter anställda till olika avdelningar som heter crosstable.
Jag vill få ut den/dom som har minst antal rader (minst kompabilitet mot en avdelning) och det är inga problem.
Problemet uppstår när det är fler än 1 som har samma antal, då visar min hämtning bara den som ligger först i databasen.
Hur bör jag gå tillväga för att få ut alla 'person_id' som har lägst rader i min tabell?

Sedan vill jag slumpa fram en av dom här som jag placerar i en avdelning som dom är kompatibla mot.

<?php include "conn.php"; include "functions.php"; countCompatible($mysqli); $result = mysqli_query($mysqli,"SELECT *, COUNT(*) as antal FROM crosstable GROUP BY person_id;"); while($row = mysqli_fetch_array($result)) { echo "<b>Person: ".$row['person_id']." Antal: ".$row['antal']."</b><br>"; $array[$row['person_id']] = $row['antal']; } $lowestSections = min($array); $test = array_search('1', $array); //Här vill jag få ut "Den/dom här personerna har lägst antal kompatibla avdelningar" echo "<br>Den här personen ".$test." har lägst antal kompatibla avdelningar"; ?> [/php]

Hej,

Om du bara vill få ut den personen med lägst antal rader borde du kunna sortera och begränsa det direkt i sql frågan genom SORT BY ASC (ASC = Ascending dvs lägst till högst), typ någonting sånt här:

<?php include "conn.php"; include "functions.php"; countCompatible($mysqli); $result = mysqli_query($mysqli,"SELECT *, COUNT(*) as antal FROM crosstable GROUP BY person_id ORDER BY antal ASC LIMIT 1;"); $row = mysqli_fetch_array($result); echo "<br>Den här personen ".$row['person_id']." har lägst antal kompatibla avdelningar"; ?>

Visa signatur

Dator, MOBO: Asus X99-A, CPU: Intel I7 6800k (3.4GHz), GPU: Geforce PNY 2070 Super, RAM: 4x8GB Corsair Vengeance LPX 2400MHz, OS-HDD: Intel 750 PCIe 400GB, PSU: EVGA SuperNOVA G2 850W

Permalänk

Jag skulle behöva hjälp av någon som kan ta sig tid att läsa igenom min kod och förklara varför den inte placerar ut alla anställda till avdelningarna. Jag upptäckte att den ibland betedde sig annorlunda när jag refreshade sidan, istället för att "refresha" loopen i koden. Någon gång ibland placerar den ut alla, men senaste gångerna har den lämnat 3 stycken utan avdelning, och inte tagit hänsyn till att vissa avdelningar stått tomma.

Filen som genererar och placerar anställda till olika avdelningar

<?php include "conn.php"; include "functions.php"; if(isset($_POST['reset'])) { $panic = "UPDATE personer SET booked=0"; mysqli_query($mysqli, $panic); $panic2 = "UPDATE avdelningar SET max=0"; mysqli_query($mysqli, $panic2); }elseif(isset($_POST['save'])) { //Backup "generate" to table 'avdelningar' (=sections in swedish) "lastsection" to prevent employee to end up at the same section as yesterday backupToLastSection($mysqli); } ?> <html> <form action="generate.php" method="post"> <input type=submit name="reset" value="Reset"> </form> </html> <?php $sql = "UPDATE avdelningar SET max = 0}"; mysqli_query($mysqli, $sql); //Main loop, loop until all sections are filled with employees $loopstatus = true; //Counter, how many times it should take to complete the task, i need to find another solution $v = 0; while($loopstatus) { $array = []; $v = $v + 1; //Check if all sections are filled with employees $test = "SELECT * FROM avdelningar"; $test2 = (mysqli_query($mysqli, $test)); while($rowe = mysqli_fetch_array($test2)) { //If all sections are NOT filled with employees if($rowe['max'] == '0') { echo "Om alla avdelningar INTE är tillsatta<br>"; $loopstatus = true; } //Group number of unique person_id in crosstable $result = mysqli_query($mysqli,"SELECT *, COUNT(*) as antal FROM crosstable GROUP BY person_id;"); //Loop number of unique person_id in crosstable, number of people that are available for any sections //Create array containing employee id[number of available sections] while($row = mysqli_fetch_array($result)) { //Get number from 'crosstable' count by 'sum person_id as group' $result2 = "SELECT * FROM personer WHERE id = {$row['person_id']}"; $resultat = mysqli_fetch_assoc(mysqli_query($mysqli, $result2)); if($resultat['booked'] == 0 && $resultat['away'] == 0) { $array[$row['person_id']] = $row['antal']; echo "Om resultat bokad = 0 och away = 0: Person ID ".$row['person_id']." och Antal ".$row['antal']."<br>"; } } //If not all employees are assigned a section, in other words if the array is NOT empty if(count($array) > 0) { //Count people with lowest number of sections in crosstable $employeeLowestSectionCount = array_keys($array, min($array)); echo "employeeLowestSectionCount "; print_r($employeeLowestSectionCount); $adaptedcount = count($employeeLowestSectionCount); echo "<br>adaptedcount: ".$adaptedcount."<br>"; //Variabel that contains number of people with lowest number of compatible sections if($adaptedcount != 0) { //Random employee $random = rand(0, ($adaptedcount - 1)); echo "Random: ".$random."<br>"; //Random section id $result3 = "SELECT section_id FROM crosstable WHERE person_id={$employeeLowestSectionCount[$random]} ORDER BY RAND() LIMIT 1"; $query = mysqli_fetch_assoc(mysqli_query($mysqli, $result3)); if(checkSectionNotFull($mysqli, $query['section_id']) == false) { $connstring2 = "SELECT * FROM avdelningar WHERE id = {$query['section_id']}"; $data2=mysqli_fetch_assoc(mysqli_query($mysqli, $connstring2)); //If section has NOT been assigned max number of employees(1=section full or 0=not full) if($data2['max'] == 0) { echo "Det fanns plats på avdelning".$query['section_id']." för ".$employeeLowestSectionCount[$random]." Uppdaterar DB!<br><br>"; //Update database writeToDatabase($mysqli, $query['section_id'], $employeeLowestSectionCount[$random]); }else { echo "Fanns ej plats, uppdaterar ej DB!<br><br>"; } }else { //Update section to status "full" $sql = "UPDATE avdelningar SET max = 1 WHERE id = {$query['section_id']}"; mysqli_query($mysqli, $sql); //Check if the code/program is "satisfied" with all employee assignments if(checkAllAssigned($mysqli) == 1) { $loopstatus = false; echo "Uppfyllda!!"; } } } }else { $loopstatus = false; echo "Det verkar vara slut!"; } } //There must be some kind of "LIMIT" if the program cant achieve an optimal combination of employees / sections //I really don't know how to set this, so I just wrote one temporarily manually if($v > 70) { echo "<script>window.location.replace('generate.php');</script>"; echo "Antal gånger programmet har körts: ".$v; } if($loopstatus = false) { ?> <script> window.location.replace("index.php"); </script> <?php } } ?>

Mina funktioner

<?php include "conn.php"; function checkAllAssigned($mysqli) { //Räkna antalet totala platser på alla avdelningar $sql = "SELECT SUM(platser) as 'antal' FROM avdelningar"; $query = mysqli_query($mysqli, $sql); $antalPlatser = mysqli_fetch_array($query); //Räkna antal bokade personer $sql = "SELECT COUNT(*) as antal FROM personer WHERE booked != 0"; $query = mysqli_query($mysqli, $sql); $antalBokade = mysqli_fetch_assoc($query); //Räkna antalet tillgängliga personer $sql = "SELECT COUNT(*) as antal FROM personer WHERE booked = 0 AND away = 0"; $query = mysqli_query($mysqli, $sql); $antalAvail = mysqli_fetch_assoc($query); //Om antalet bokade personer är lika med totala antalet platser if($antalBokade['antal'] == $antalPlatser['antal']){ return 1; //Om antalet tillgängliga personer är mindre än totala antalet platser OCH antal bokade är lika med antalet tillgängliga }elseif($antalAvail['antal'] < $antalPlatser['antal'] && $antalBokade['antal'] == $antalAvail['antal']) { return 1; //Om antalet tillgängliga personer är fler än totala antalet platser }elseif($antalAvail['antal'] > $antalPlatser['antal'] && $antalBokade['antal'] == $antalPlatser['antal']) { return 1; }else { return 0; } } function checkSectionNotFull($mysqli, $section) { //Hämta från avdelningar $test1 = mysqli_query($mysqli, "SELECT * FROM avdelningar"); while($rad = mysqli_fetch_array($test1)) { if($section == $rad['id']) { echo "Avd id: ".$rad['id']." <br>Antal platser avdelning ".$rad['platser']." <br>"; //Räkna hur många som är bokade till varje avdelning $result = mysqli_query($mysqli,"SELECT *, COUNT(*) as antal FROM personer WHERE booked = {$rad['id']} GROUP BY booked LIMIT 1;"); while($rad2 = mysqli_fetch_array($result)) { if($rad['platser'] - $rad2['antal'] == 0) { return true; }else { return false; } } } } } function writeToDatabase($conn, $booked, $id) { $dbString = "UPDATE personer SET booked = {$booked} WHERE id = {$id}"; echo $dbString; mysqli_query($conn, $dbString) or die(); } //Räkna antal totala personer som är kompatibla mot någon avdelning function countCompatible($conn) { $lowestSections = "SELECT COUNT(DISTINCT person_id) as number FROM crosstable"; $result = mysqli_query($conn, $lowestSections); while($row = mysqli_fetch_array($result)) { return $row['number']; } } function backupToLastSection($mysqli) { $sqlcopy = "UPDATE personer SET lastsection = booked"; mysqli_query($mysqli, $sqlcopy); } //SELECT count(*) as total from personer function countSQL($db, $connstring) { $connstring = mysqli_query($db, $connstring); $data=mysqli_fetch_assoc($connstring); return $data['total']; } function updateSQL($db, $updatestring) { if ($db->query($updatestring) === TRUE) { echo "Uppdatering \"".$updatestring."\" genomförd!"; } else { echo "Uppdateringen \"".$updatestring."\" misslyckades!" . $conn->error; } } function randSection($db, $id) { $resultpeople = mysqli_query($db,"SELECT * FROM personer WHERE id = {$id}"); $resultsections = mysqli_query($db,"SELECT * FROM avdelningar"); $countpeople = countSQL($db, "SELECT count(*) as total from personer"); $countsections = countSQL($db, "SELECT count(*) as total from avdelningar"); while($row = mysqli_fetch_array($resultpeople)) { for($i=1; $i <= $countpeople; $i++) { echo "<br>i: ".$i.""; } } while($row2 = mysqli_fetch_array($resultsections)) { echo "<br>Platser: ".$row2['platser']; } for($j=1; $j <= $countsections; $j++) { echo "<br>j: ".$j.""; } } ?>

Permalänk
Hedersmedlem
Skrivet av RobinJacobsson:

[...]Jag upptäckte att den ibland betedde sig annorlunda när jag refreshade sidan, istället för att "refresha" loopen i koden. Någon gång ibland placerar den ut alla, men senaste gångerna har den lämnat 3 stycken utan avdelning, och inte tagit hänsyn till att vissa avdelningar stått tomma.

Här har du egentligen en ganska bra idé om var och hur någonting går fel.

Nu har jag bara ögat igenom koden lite, men baserat på det du säger så låter det som att det är någon UPDATE som spökar och sätter in värden på någon form av felaktigt sett.
Börja med att titta där den ska skriva ut avdelning (och speciellt den plats som skriver ut om det är tomt) och börja söka baklänges.

Hett tips kan vara att tömma testdata och köra om det från scratch för att kunna reproducera buggen, undelättar felsökningen enormt.

Lycka till!

Visa signatur

Dator, MOBO: Asus X99-A, CPU: Intel I7 6800k (3.4GHz), GPU: Geforce PNY 2070 Super, RAM: 4x8GB Corsair Vengeance LPX 2400MHz, OS-HDD: Intel 750 PCIe 400GB, PSU: EVGA SuperNOVA G2 850W

Permalänk

Eller kan det vara den funktionen som kollar om alla avdelningar är satta? Kolla gärna på den också om jag har satt alla villkor rätt!

Skickades från m.sweclockers.com

Permalänk

Nu har jag nog lyckats åtgärda felet och den verkar placera ut folk som den ska äntligen!

Nu återstår två problem som jag hoppas att någon kan hjälpa mig med!

1. Jag behöver ett sätt för loopen att veta om den har fastnat, dvs om sista personen/personerna att slumpas inte har något kompatibel avdelning och att loopen således behöver börja om och slumpa ut alla från början.

2. Att den tar hänsyn till vart man var under gårdagen (eller förra utfallet). Det anges i tabellen "personer" under kolumnen "last_section" och representeras av en siffra som motsvarar kolumnen "id" i tabellen "avdelningar".

Här är den senaste koden:

Edit: jag upptäckte också att den inte verkar uppdatera alla kolumner som säger om en avdelning är fullsatt eller ej (rad 135 i koden).
Men det verkar som att den placerar ut och tar hänsyn till om avdelningen är full ändå, även om inte alla max=0 i tabellen avdelningar.
$sql = "UPDATE avdelningar SET max = 1 WHERE id = {$query['section_id']}";

<?php include "conn.php"; include "functions.php"; //Om do=generate if(isset($_POST['reset']) && isset($_GET['do']) == 'generate') { $panic = "UPDATE personer SET booked=0"; mysqli_query($mysqli, $panic); $panic2 = "UPDATE avdelningar SET max=0"; mysqli_query($mysqli, $panic2); ?> <script> window.location.replace("generate.php"); </script> <?php //Om do=save }elseif(isset($_POST['save']) && isset($_GET['do']) == 'save') { //Backup "generate" to table 'avdelningar' (=sections in swedish) "lastsection" to prevent employee to end up at the same section as yesterday backupToLastSection($mysqli); echo "Har sparat!"; //Annars kör programmet }else { ?> <html> <form action="generate.php?do=generate" method="post"> <input type=submit name="reset" value="Reset"> </form> </html> <?php $sql = "UPDATE avdelningar SET max = 0}"; mysqli_query($mysqli, $sql); //Main loop, loop until all sections are filled with employees $loopstatus = true; //Counter, how many times it should take to complete the task, i need to find another solution $v = 0; while($loopstatus) { //Check if the code/program is "satisfied" with all employee assignments if(checkAllAssigned($mysqli) == 1) { $loopstatus = false; echo "checkAllAssigned = 1, bryt loopen!"; } $v = $v + 1; //Check if all sections are filled with employees $test = "SELECT * FROM avdelningar"; $test2 = (mysqli_query($mysqli, $test)); while($rowe = mysqli_fetch_array($test2)) { //If all sections are NOT filled with employees if($rowe['max'] == '0') { echo "Om alla avdelningar INTE är tillsatta<br>"; } //Group number of unique person_id in crosstable $result = mysqli_query($mysqli,"SELECT *, COUNT(*) as antal FROM crosstable GROUP BY person_id;"); $array = []; //Loop number of unique person_id in crosstable, number of people that are available for any sections //Create array containing employee id[number of available sections] while($row = mysqli_fetch_array($result)) { //Get number from 'crosstable' count by 'sum person_id as group' $result2 = "SELECT * FROM personer WHERE id = {$row['person_id']}"; $resultat = mysqli_fetch_assoc(mysqli_query($mysqli, $result2)); if($resultat['booked'] == 0 && $resultat['away'] == 0) { $array[$row['person_id']] = $row['antal']; echo "Om resultat bokad = 0 och away = 0: Person ID ".$row['person_id']." och Antal ".$row['antal']."<br>"; } } //If not all employees are assigned a section, in other words if the array is NOT empty if(count($array) > 0) { //Count people with lowest number of sections in crosstable $employeeLowestSectionCount = array_keys($array, min($array)); echo "employeeLowestSectionCount "; print_r($employeeLowestSectionCount); $adaptedcount = count($employeeLowestSectionCount); echo "<br>adaptedcount: ".$adaptedcount."<br>"; //Variabel that contains number of people with lowest number of compatible sections if($adaptedcount != 0) { //Random employee $random = rand(0, ($adaptedcount - 1)); echo "Random: ".$random."<br>"; //Random section id $result3 = "SELECT section_id FROM crosstable WHERE person_id={$employeeLowestSectionCount[$random]} ORDER BY RAND() LIMIT 1"; $query = mysqli_fetch_assoc(mysqli_query($mysqli, $result3)); if(checkSectionNotFull($mysqli, $query['section_id']) == false) { $connstring2 = "SELECT * FROM avdelningar WHERE id = {$query['section_id']}"; $data2=mysqli_fetch_assoc(mysqli_query($mysqli, $connstring2)); //If section has NOT been assigned max number of employees(1=section full or 0=not full) if($data2['max'] == 0) { echo "Det fanns plats på avdelning".$query['section_id']." för ".$employeeLowestSectionCount[$random].", Uppdaterar DB!<br><br>"; //Update database writeToDatabase($mysqli, $query['section_id'], $employeeLowestSectionCount[$random]); }else { echo "Fanns ej plats, uppdaterar ej DB!<br><br>"; } }else { //Update section to status "full" $sql = "UPDATE avdelningar SET max = 1 WHERE id = {$query['section_id']}"; mysqli_query($mysqli, $sql); echo "Uppdatera avdelningar set max 1 där id = ".$query['section_id']."<br>"; } } } } if($loopstatus == false) { echo "Loopen verkar ha fyllt databasen på ".$v."st vändor!"; } echo "V har körts: ".$v." gång!<br>"; } ?> <form action="generate.php?do=save" method="post"> Spara? <input type=submit name="save" value="Spara"> </form> <?php } ?>