简体   繁体   中英

The best way to display data in a table

Getting a little bit outside my comfort zone and I'm hoping someone can explain the best way of achieving what I need.

This is a very simple staff attendance system.

The staff table includes the name of the staff member.

The attendance table includes the date and type of shift they worked (full/half/day-and-a-half) on that day.

What I now want to do is create a report as a table that shows all the staff's attendance between two dates (a pay period).

I'm thinking the first column should be the staff names, and then subsequent columns would be headed with each date between the two dates (start_date and end_date) and I then want to populate the rest of the table with the shift that a member of staff worked on a particular date.

So, it would look something like this:

     Name     |  2013-05-26  |   2013-05-27   |   etc
     -------------------- ---------------------------
     John     |     full     |      half      |
     Mary     |     off      |      full      |
     Peter    |     half     |      full      |

The following query gives me all the data:

SELECT a.id, first_name, last_name, attDate, staff_id, att, late
FROM staff as a LEFT OUTER JOIN staff_attendance AS b
  ON a.id = b.staff_id 
    AND b.`attDate` >= '2013-05-26' 
    AND  b.`attDate` <= '2013-06-27' 
ORDER BY last_name, attDate;

Which would basically be:

    id  |   first_name   | last_name |  attDate    | staff_id | att   |  late
    ------------------------------------------------------------------------
    1   |     John       |    smith  | 2013-05-26  |     1    | full  |    0
    1   |     John       |    smith  | 2013-05-27  |     1    | half  |    0
    2   |     Mary       |    Jones  | 2013-05-26  |     2    | off   |    0
    2   |     Mary       |    Jones  | 2013-05-27  |     2    | full  |    0
    3   |     Peter      |    Doe    | 2013-05-26  |     3    | half  |    0
    3   |     Peter      |    Doe    | 2013-05-26  |     3    | full  |    0

So as you can see, I have all the data, I just have no idea how to get it into the table.

Any thoughts or suggestions very welcome.

Many thanks

Graeme

Following advice from dev-null-dweller, I have the following code:

    $dbh = new PDO("mysql:host=$hostname;dbname=web14-fresh", $username, $password);
    $sql = "SELECT a.id, first_name, last_name, attDate, staff_id, att, late FROM staff as a LEFT OUTER JOIN staff_attendance AS b ON a.id = b.staff_id AND b.`attDate` >= '" .                   $startdate. "' AND  b.`attDate` <= '". $enddate . "' ORDER BY last_name, attDate;";
    $stmt = $dbh->query($sql);

    $dates = array();
    $users = array();

    while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
        $dates[] = $row['attDate'];
        if (!isset($users[$row['id']])) {
            $users[$row['id']] = array(
                'first_name' => $row['first_name'], 
                'last_name' => $row['last_name'],
                'attendance' => array()
            );
        }
        $users[$row['id']]['attendance'][$row['attDate']] = $row['att'];
    }

    $dates = array_unique($dates);
    sort($dates);

    // header
    echo '<table border=1><tr>';
    echo '<td>Name</td>';
    foreach($dates as $d){
        echo '<td>'.$d.'</td>';
    }
    echo '</tr>';

    //data
    foreach($users as $u) {
        echo '<tr><td>'.$u['first_name'].'</td>';
        foreach($dates as $d) {
            if (isset($u['attendance'][$d])) {
                echo '<td>'.$u['attendance'][$d].'</td>';
            } else {
                echo '<td>?</td>';
            }
        }
        //end row
        echo '</tr>';
    }
    echo '</table>';

This doesn't seem to be populating all the dates across the top and can't see why. This is what I am getting.

    Name        2013-06-26
    Katy    ?   full
    Lauren  ?   full
    Laura   ?   full
    Louise  ?   holiday
    Jade    ?   off

Not quite sure the date array is not populating correctly :-/

Piece of code to illustrate my comment :

$dates = array();
$users = array();

while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
    $dates[] = $row['attDate'];
    if (!isset($users[$row['id']])) {
        $users[$row['id']] = array(
            'first_name' => $row['first_name'], 
            'last_name' => $row['last_name'],
            'attendance' => array()
        );
    }
    $users[$row['id']]['attendance'][$row['attDate']] = $row['att'];
}

$dates = array_unique($dates);
sort($dates);

// header
//echo 'name';
foreach($dates as $d){
    echo $d;
}

//data
foreach($users as $u) {
    //echo $u['first_name'];
    foreach($dates as $d) {
        if (isset($u['attendance'][$d])) {
            echo $u['attendance'][$d];
        } else {
            // for missing records?
        }
    }
    //end row
}

Here is the basic output loop I use for outputting SQL results. It can be extended from here with conditional formatting based on the $key value or what have you.

You should also get friendly with the printf() and sprintf() functions, as they are super useful.

$rs; // assuming this is an indexed array of rows returned from your DB
// ie: $rs[0]['id']

$output = '<table>';

//print header row by iterating through the first result row and printing the keys
$output .= '<tr>';
foreach($rs[0] as $key => $value) {
  $output .= sprintf('<td>%s</td>', $key);
}
$output .= '</tr>';

//now the data rows
foreach($rs as $row) {
  $output .= '<tr>';
  foreach($row as $key => $value) {
    $output .= sprintf('<td>%s</td>', $value);
  }
  $output .= '</tr>';
}

$output .= '</table>';
echo $output;

Briefly: First query only dates to create table header. Next use your query to get data to create all rows in html table. And you have to remember first_name from previous result row. If first_name is changed you start new row in html table.

pseudocode (not complete):

$results = query("SELECT ... only dates");

// ... some html ... opening header row

foreach($results as $date) {
    echo "<td>", $date, "</td>"; 
}

$results = query("SELECT ... your query");
$last__first_name = "";

// ... some html ... closing header row and opening data rows

foreach($results as $row) {

    if( $row->first_name != $last__first_name ) {
        $last__first_name = $row->first_name;
        echo "</tr><tr>"; // create new row in html table
        echo "<td>", $row->first_name, "</td>";
    }

    echo "<td>", $row->att, "</td>"; // next column 
}

// ... some html ... closing table

You can echo the results in a HTML table. First, you create the headings:

echo '<table>';
echo '<tr><td>Column 1</td><td>Column 2</td><td>Column 3</td>......</tr>';

Then, you execute the SQL query (the SELECT):

$result = mysql_query("SELECT * FROM table ... ...");

After this, you can iterate through the results, with "while":

while ($row = mysql_fetch_array($result ) ) {
echo '<tr><td>'.$row['name_of_column_1_in_db'].'</td><td>'.$row['name_of_column_2_in_db'].'</td> .......... </tr>';
}

Then, close the table tag:

echo '</table>';

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