简体   繁体   中英

looping with a query and lookup table. mysql & php

I am having a bit of difficulty figuring out a loop.

They're not really my strong suit. ;)

It uses a class "lookup" as a lookup table that looks like this: (left out a lot of rows for brevity)

class lookup {
   protected $lookup = array(
    array('rider_count' => '1', 'heat_count' => '1', 'riders_in_heat_1' => '1'),
    array('rider_count' => '2', 'heat_count' => '1', 'riders_in_heat_1' => '2'),
    array('rider_count' => '3', 'heat_count' => '1', 'riders_in_heat_1' => '3'),
    array('rider_count' => '4', 'heat_count' => '1', 'riders_in_heat_1' => '4'),
    array('rider_count' => '5', 'heat_count' => '1', 'riders_in_heat_1' => '5'),
    array('rider_count' => '6', 'heat_count' => '1', 'riders_in_heat_1' => '6'),
    array('rider_count' => '7', 'heat_count' => '1', 'riders_in_heat_1' => '7'),
    array('rider_count' => '8', 'heat_count' => '2', 'riders_in_heat_1' => '4', 'riders_in_heat_2' => '4'),
    array('rider_count' => '9', 'heat_count' => '2', 'riders_in_heat_1' => '5', 'riders_in_heat_2' => '4'),
    array('rider_count' => '10', 'heat_count' => '2', 'riders_in_heat_1' => '5', 'riders_in_heat_2' => '5'),
    array('rider_count' => '11', 'heat_count' => '2', 'riders_in_heat_1' => '6', 'riders_in_heat_2' => '5'),
    array('rider_count' => '12', 'heat_count' => '2', 'riders_in_heat_1' => '6', 'riders_in_heat_2' => '6'),
    array('rider_count' => '13', 'heat_count' => '2', 'riders_in_heat_1' => '7', 'riders_in_heat_2' => '6'),
    array('rider_count' => '14', 'heat_count' => '2', 'riders_in_heat_1' => '7', 'riders_in_heat_2' => '7')
   );
  public function select ($field, $value)
  {
    $list = array();
    foreach ($this->lookup as $count)
    {
      if ($count[$field] == $value)
      {
        $list[] = $count;
      }
    }
    return $list;
  }
}

$classes = new lookup();

my php:

      <?php

        // get entries for the event
      function getEntries($class_id, $limit, $offset)
      {
        global $db;
        $getentries = $db->prepare("SELECT entry_id FROM tbl_event_entries WHERE event_id = :event_id AND class_id = :class_id LIMIT :offset, :limit");
        $getentries->bindValue(':event_id', $_GET['event_id']);
        $getentries->bindValue(':class_id', $class_id);
        $getentries->bindValue(':limit', $limit);
        $getentries->bindValue(':offset', $offset);
        $getentries->execute();
        while ($r = $getentries->fetch(PDO::FETCH_ASSOC)) return $r['entry_id'];
      }
        // get count of entries per class
        // get classes for the event
        $geteventclasses = $db->prepare("SELECT class_id FROM tbl_event_classes WHERE event_id = :event_id");
        $geteventclasses->bindValue(':event_id', $_GET['event_id']);
        $geteventclasses->execute();
        while ($r = $geteventclasses->fetch(PDO::FETCH_ASSOC))
        {
        $getentriesperclass = $db->prepare("SELECT entry_id FROM tbl_event_entries WHERE class_id = :class_id AND event_id = :event_id");
        $getentriesperclass->bindValue(':class_id', $r['class_id']);
        $getentriesperclass->bindValue(':event_id', $_GET['event_id']);
        $getentriesperclass->execute();
        $r2count = $getentriesperclass->rowCount();
        $counts[$r['class_id']] = $r2count;
        }
          foreach ($counts as $class => $rider_count)
          {
            $list = $classes->select('rider_count', $rider_count);

            echo "class: ".  $class ."; ridercount: " . $list[0]['rider_count'] ."; heats: ". $list[0]['heat_count'] ." heats, consisting of :<br>\n";


            for ($i = 1; $i <= $list[0]['heat_count']; $i++)
            {
              if ($list[0]['heat_count'] > 0)
              {
                for ($rih = 1; $rih <= $list[0]['riders_in_heat_'.$i]; $rih++)
                {
                  $offset = 1;
                  echo "<li>Heat ". $i ." : ". getEntries($class, $list[0]['riders_in_heat_'.$i], $offset) ." </li>";
                }
                $offset = $offset + $list[0]['riders_in_heat_'.$i];
              }

            }
              echo "</ul>";
          }
       ?>

This will eventually build an update query to assign "heat_nbr" and "heat_position" to each entry_id.

The task is to take rider_count from a class_id and break it up so that we only have a max of 7 riders per heat race and evenly distribute riders to each heat.

The lookup is how we determine how the distribution happens. That part seems working perfectly. I'm just stuck on how to get each rider assigned to a position.

I've tried several different methods and this is as close as I have gotten to the answer.

A nudge in the right direction would be much appreciated!

See the output of what I have so far here:

http://home.garyeterry.com/midam/createheats.php?event_id=113

Thanks

table structure:

CREATE TABLE IF NOT EXISTS `tbl_event_entries` (
 `entry_id` int(11) NOT NULL AUTO_INCREMENT,
 `event_id` int(1) DEFAULT NULL,
 `racer_id` int(4) DEFAULT NULL,
 `class_id` int(1) DEFAULT NULL,
 `racing_nbr` varchar(4) DEFAULT NULL,
 `machine_cc` int(2) DEFAULT NULL,
 `brand_id` int(1) DEFAULT NULL,
 `overall_finish` int(1) DEFAULT NULL,
 `xtra_int1` varchar(10) DEFAULT NULL,
 `heat_nbr` int(1) DEFAULT NULL,
 `heat_position` int(1) DEFAULT NULL,
 `heat_row` int(1) DEFAULT NULL,
 `heat_finish` int(1) DEFAULT NULL,
  PRIMARY KEY (`entry_id`),
  UNIQUE KEY `entry_id` (`entry_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=165 ;

Did my best to clean things up, might not be perfect, but should suffice as a nudge in the right direction.

Move lookup class to DB table

It seems to me like you'd be much better served here moving the intent of the lookup class into a database table. Imagine something like this:

CREATE TABLE IF NOT EXISTS `tbl_lookup` (
 `lookup_id` int(11) NOT NULL AUTO_INCREMENT,
 `rider_count` int NOT NULL,
 `heat_count` int NOT NULL,
 `riders_in_heat_1` int NOT NULL,
 `riders_in_heat_2` int,
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

then insert all your data from the lookup class.

Use JOINs & GROUP BY in your first SQL query

You need to determine the number of riders in a given event and class. You can just JOIN tbl_event_classes and tbl_event_entries then GROUP BY tbl_event_entries.event_id to get those counts.

SELECT tec.class_id, tec.event_id, COUNT(tee.event_id) AS entries_per_class
FROM tbl_event_classes tec
JOIN tbl_event_entries tee ON tee.event_id = tec.event_id
WHERE tec.event_id = :event_id
GROUP BY tee.event_id

Cleaning up the PHP

Now your PHP code should be a bit easier to follow. One main query to get the events and classes with the number of riders per event per class. Then as you loop over that result set, determine the number of riders per heat.

This is a little rough, but I'm sure you can get it polished up from here.

function getEntriesPerClass($event_id) {
    global $db;

    $stmt = $db->prepare(
        'SELECT tec.class_id, tec.event_id, COUNT(tee.event_id) AS entries_per_class ' .
        'FROM tbl_event_classes tec ' .
        'JOIN tbl_event_entries tee ON tee.event_id = tec.event_id ' .
        'WHERE tec.event_id = :event_id ' .
        'GROUP BY tee.event_id');

    $stmt->bindValue(':event_id', $event_id);
    $stmt->execute();

    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

function getRidersInHeats($class_id, $event_id, $riders_per_class)
{
    global $db;

    $stmt = $db->prepare(
        'SELECT tl.riders_in_heat_1, tl.riders_in_heat_2 ' .
        'FROM tbl_lookup ' .
        'WHERE class_id = :class_id AND event_id = :event_id AND rider_count = :entries');

    $stmt->bindValue(':class_id', $class_id);
    $stmt->bindValue(':event_id', $event_id);
    $stmt->bindValue(':rider_count', $riders_per_class);

    $stmt->execute();

    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

$entriesPerClass = getEntriesPerClass($_GET['event_id']);
foreach($entriesPerClass as $entry) {
    $riders = getRidersInHeats($entry['class_id'], $entry['event_id'], $entry['entries_per_class']);

    echo
        "class     : " . $row['class_id']       . "; " .
        "ridercount: " . $riders['rider_count'] . "; " .
        "heats     : " . $riders['heat_count']  . "<br/>";

    echo "Heats, consisting of :<br>\n<ul>";
    echo "<li>Heat 1: " . $riders['riders_in_heat_1'] . "</li>";

    $ridersInHeat2 = $riders['riders_in_heat_2'];
    if($ridersInHeat2 > 0) {
        echo "<li>Heat 2: " . $riders['riders_in_heat_2'] . "</li>";
    }

    echo "</ul>";
}

I kept at it this morning, knowing that the loop was my problem and knowing I was close to what I need. A little massaging of the $offset in my main loop and it's working as I need it to. ;)

Thanks again for those that offered help. Below is the code that works.

<?php
session_start();
require_once "../db.class.php";
require_once "../functions.class.php";

$f = new functions();
$event_id = $_POST['id'];
header("Content-Type:application/json; Charset=utf-8");


// -- Function Name : getLookup
// -- Params : $value
// -- Purpose : get count of riders and return distribution of riders and heats
function getLookup($value)
{
    global $db;
    $stmt = $db->prepare("SELECT * FROM tbl_lookup WHERE rider_count = :value");
    $stmt->bindValue(':value', $value);
    $stmt->execute();
    return $r = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// -- Function Name : getEntries
// get entries for the event
// -- Purpose : get entries to determine race orders
function getEntries($class_id, $limit, $offset)
{
    global $db;
    global $event_id;
    $getentries = $db->prepare("SELECT entry_id FROM tbl_event_entries WHERE event_id = :event_id AND class_id = :class_id LIMIT :offset, :limit");
    $getentries->bindValue(':event_id', $event_id);
    $getentries->bindValue(':class_id', $class_id);
    $getentries->bindValue(':limit', $limit);
    $getentries->bindValue(':offset', $offset);
    $getentries->execute();
    while ($r = $getentries->fetch(PDO::FETCH_ASSOC)) return $r['entry_id'];
}
// -- Function Name : getEntriesPerClass
// get count of entries per class
// -- Purpose : get entries per class to feed the lookup function  
function getEntriesPerClass ()
{
    global $db;
    $getentriesperclass = $db->prepare("SELECT tbl_event_entries.class_id, COUNT(tbl_event_entries.entry_id) AS riders, tbl_moto_order.moto_nbr
                                FROM tbl_event_entries
                                JOIN tbl_moto_order ON tbl_event_entries.event_id = tbl_moto_order.event_id AND tbl_event_entries.class_id = tbl_moto_order.class_id
                                WHERE tbl_event_entries.event_id = :event_id
                                GROUP BY tbl_event_entries.class_id
                                ORDER BY moto_nbr;");
    $getentriesperclass->bindValue(':event_id', $_POST['id']);
    $getentriesperclass->execute();
    $counts = array();
    while ($r = $getentriesperclass->fetch(PDO::FETCH_ASSOC)) $counts[$r['class_id']] = $r['riders'];
    return $counts;
}

$counts = getEntriesPerClass();
$race = 1; //set to add value to race_nbr field, increments 1 time for each total heat race

foreach ($counts as $class => $rider_count)
{
    $list = getLookup($rider_count); // lookup to get heat race counts and line ups for each heat.
    // update event classes table with counts so we don't have to loop like crazy to build the printouts
    $assign_class_counts = $db->prepare("UPDATE tbl_event_classes SET nbr_of_heats = :nbr_of_heats, nbr_of_riders_in_heats = :nbr_of_riders_in_heats WHERE event_id = :event_id AND class_id = :class_id");
    $assign_class_counts->bindValue(':nbr_of_heats', $list[0]['heat_count']);
    $assign_class_counts->bindValue(':nbr_of_riders_in_heats', $list[0]['rider_count']);
    $assign_class_counts->bindValue(':event_id',  $_POST['id']);
    $assign_class_counts->bindValue(':class_id', $class);
    $assign_class_counts->execute();

    $offset = 0; // set offset to feet the main query to give us the position in each heat for a rider. Used in the getEntries query.
    for ($i = 1; $i <= $list[0]['heat_count']; $i++)
    {
        if ($list[0]['heat_count'] > 0)
        {
            for ($rih = 1; $rih <= $list[0]['riders_in_heat_'.$i]; $rih++)
            {
                $assignheats = $db->prepare("UPDATE tbl_event_entries SET heat_nbr = :heat_nbr, heat_position = :heat_position, race_nbr = :race_nbr WHERE entry_id = :entry_id");
                $assignheats->bindValue(':heat_nbr', $i);
                $assignheats->bindValue(':heat_position', $rih);
                $assignheats->bindValue(':race_nbr', $race);
                $assignheats->bindValue(':entry_id', getEntries($class, $list[0]['riders_in_heat_'.$i], $offset));
                $assignheats->execute();
                $offset++;
            }
            $race++;
        }
    }
}

echo json_encode(array('status' => true));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM