我有以下记录集:
Date |Role |Name
=============================
01/02/14 |Musician |Bob
01/02/14 |Leader |Jerry
01/02/14 |Singer |Carol
08/02/14 |Musician |Charles
08/02/14 |Leader |Baz
08/02/14 |Singer |Norman
我希望数据显示为rota / roster格式。 EG。
Role |01/02/14 |08/02/14
===============================
Musician |Bob |Charles
Leader |Jerry |Baz
Singer |Carol |Norman
理想情况下,我希望在不更改MySQL查询的情况下在php中完成。
这是我到目前为止所得到的,但它并不是很有用。
$temprole='norole';
$newkey=0;
echo "<table><tr>";
foreach ($result as $key => $val) {
echo "<td>" . $val['date'] . "</td>";
if ($temprole==$val['role_name']){ //is the same role?
} else {
//If the role name is different, print the role column
echo $val['role_name'] . "</br>";
}
$temprole = $val['role_name'];
}
echo "</tr></table>";
echo "<hr>";
答案 0 :(得分:2)
善良,这很有趣......: - /
这是经过测试的代码,可以根据需要执行。有很多评论。随意删除它们以更清楚地看到代码。无论...
您应该能够更改$ allRoles数组以使角色以不同的顺序打印。我试过了,效果很好。
它在Windows XP(XAMPP)上运行PHP 5.3.18。
添加了一些css以使表格更清晰。
更改了代码以从'mysqli'查询而不是数组
中读取数据查看标有'!important'的行,以确保其正常工作。
示例输出:
Roles 01/02/14 05/02/14 08/02/14
musician Bob Donald Charles
leader Jerry -- Baz
singer Carol Freddy Norman
代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Q2220229 - Pivot table</title>
<style>
td {
border-bottom: 1px solid grey;
width: 10em;
}
</style>
</head>
<body>
<?php
/*
* Some test data base on:
* Date |Role |Name
=============================
01/02/14 |Musician |Bob
01/02/14 |Leader |Jerry
01/02/14 |Singer |Carol
08/02/14 |Musician |Charles
08/02/14 |Leader |Baz
08/02/14 |Singer |Norman
*
*/
/* sample output:
*
* Role |01/02/14 |08/02/14
===============================
Musician |Bob |Charles
Leader |Jerry |Baz
Singer |Carol |Norman
*/
$db = mysqli_connect('localhost', 'test', 'test', 'testmysql');
// 1) Must return three columns only.
// 2) Can return any number of 'roles' - one per row
// 3) Any date range but beware you may need a wide page!
// 4) Must sort by date!
$query = mysqli_query($db, "SELECT service_date, role, member FROM role_by_date ORDER BY service_date ASC, role ASC");
// i prefer to used named subscripts to make the code easier to read.
// These MUST match up with column alias from the above query!
define('THE_DATE', 'service_date'); // !important
define('ROLE', 'role'); // !imortant
define('MEMBER', 'member'); // !important
/*
* Now, we need a complete array of Roles in the order that they are to be displayed.
*
* These names must match with the names of the roles in the input data.
* They will be printed out in the order that they appear in the array.
*
* These are the only roles that will appear in the $outputDates array.
* Add more and in any order to control which 'roles' are shown.
*
*/
$allRoles = array('musician', 'leader', 'singer'); // !important
/*
* At some point we will need an output array that we can easily traverse and
* print out as a row of dates. i.e. a 'page' of data.
*
* We will build it up as we go along...
*/
$outputDates = array(); // !important -- this is the 'pivoted' output array
/*
* Start to process the input data.
*
* To make my life easier, i will use the 'read ahead' technique to simplify the code.
*/
$currentInputRow = mysqli_fetch_array($query);
while (isset($currentInputRow[THE_DATE])) { // process all the input array...
// must be a new day...
$currentDay = $currentInputRow[THE_DATE];
// create an array to hold ALL the possible roles for this day...
$theDayRoles = array();
// initialise the array with default values for all the requested roles.
foreach ($allRoles as $role) {
$theDayRoles[$role] = '--';
}
// now we need to fill theDayRoles with what we actually have for the current day...
while ($currentInputRow[THE_DATE] == $currentDay) { // loop around all records for the current day
// set the appropiate DayRole to the current MEMBER
$theDayRoles[$currentInputRow[ROLE]] = $currentInputRow[MEMBER];
// read the next input row - may be current day, new day or no more
$currentInputRow = mysqli_fetch_array($query);
}
// end of day on the input for whatever reason...
/* we now have:
* 1) Current Date
*
* 2) an array of members for ALL the roles on that day.
*
* We need to output it to another array ($outputDates) where we can print it out
* by scanning the array line by line later.
*
* I will 'pivot' the array and produce an output array we can scan sequentially later.
*/
// to ensure that we are updating the correct $outputDates row i will use a subscript
$currentOutputRowIdx = 0;
// first add the current date to the output...
$outputDates[$currentOutputRowIdx][] = $currentDay;
$currentOutputRowIdx++; // next output row
// we need to drive off the '$allRoles' array to add the role data in the correct order
foreach ($allRoles as $outRole) {
$outputDates[$currentOutputRowIdx][] = $theDayRoles[$outRole];
$currentOutputRowIdx++; // next output row
}
} // end of all the input data
/*
* Now we just need to print the outputDates array one row at a time...
*/
// need the roles as the first column...
// so we need an index for which one we are currently printing
$currentRoleIdx = -1; // increment each time but allow for the first row being the title 'Roles'
echo '<table>';
foreach ($outputDates as $oneOutputRow) {
echo '<tr>';
// this is the first column...
if ($currentRoleIdx < 0) {
echo '<td>'. 'Roles' .'</td>';
}
else {
echo '<td>'. $allRoles[$currentRoleIdx] .'</td>';
}
// now output the day info
foreach($oneOutputRow as $column) {
echo '<td>'. $column .'</td>';
}
echo '</tr>';
$currentRoleIdx++; // next output Role to show...
}
echo '</table>';
?>
</body>
</html>
答案 1 :(得分:1)
<?php
echo '<div align=left>';
//initialize three arrays to hold the values
$x_role = array();
$y_date = array();
$val_name = array();
//store values from the database into three separate arrays NB theRole,
// theDate and theName are the column names from the database
foreach($data as $recordset)
{
$x_role[] = $recordset->theRole;
$y_date[] = $recordset->theDate;
$val_name[$recordset->theRole][$recordset->theDate] = $recordset->theName;
}
//get unique values for row and column and sort them if necessary
$unique_x_role = array_unique($x_role);
//asort($unique_x_role);
$unique_y_date = array_unique($y_date);
//asort($unique_y_date);
// prints table - OUTPUT
echo '<p>';
echo '<hr size=10 color=#6f9171 width=100% align=left>';
echo '<p>';
echo '<div align=left>';
echo '<table border=3 >';
echo '<tr>';
echo '<td>ROLE</td>';//prints 'ROLE" in upper left corner of table
foreach($unique_y_date as $theDate)
{
echo '<td>'.$theDate.'</td>';//prints column headings
}
echo '</tr>';//closes column headings
foreach($unique_x_role as $theRole)
{
echo '<tr>';
echo '<td>'.$theRole.'</td>'; //prints row title
foreach($unique_y_date as $theDate)
{
if(isset($val_name[$theRole][$theDate]))// checks if value exists
{
$v = $val_name[$theRole][$theDate];
echo '<td>'.$v.'</td>'; //prints name because it exists
}
else
{
echo '<td> - </td>';// prints a dash if no name exists
}
}//foreach($y_date as $theDate)
echo '</tr>';
}//foreach($unique_x_role as $theRole)
echo '</table>';
echo '</div>';
?>
答案 2 :(得分:0)
...这很有趣。我决定将所需的输出复制为原始文本,而不是将HTML复制为个人挑战。
从本质上讲,数据形成为参考数组,然后进行内爆或迭代打印所需的交叉表布局。 $columnWidth
变量允许轻松调整整个表的大小。 str_pad()
用于中心对齐。当各自的值不存在时,空合并运算符(??
)用于回退到-
。
代码:(Demo)
//It is assumed that the sql is perfectly capable of sorting by date ASC, role ASC, name ASC
$resultSet = [
['date' => '01/02/14', 'role' => 'Leader', 'name' => 'Jerry'],
['date' => '01/02/14', 'role' => 'Musician', 'name' => 'Bob'],
['date' => '01/02/14', 'role' => 'Singer', 'name' => 'Carol'],
['date' => '08/02/14', 'role' => 'Leader', 'name' => 'Baz'],
['date' => '08/02/14', 'role' => 'Leader', 'name' => 'Gaz'],
['date' => '08/02/14', 'role' => 'Leader', 'name' => 'Haz'],
['date' => '08/02/14', 'role' => 'Musician', 'name' => 'Charles'],
['date' => '08/02/14', 'role' => 'Singer', 'name' => 'Norman'],
['date' => '15/02/14', 'role' => 'Astronaut', 'name' => 'Neil'],
];
$columnWidth = 20;
foreach ($resultSet as ['date' => $date, 'role' => $role, 'name' => $name]) {
$nested[$date][$role][] = $name;
$dates[$date] = str_pad($date, $columnWidth, " ", STR_PAD_BOTH);
$roles[$role] = str_pad($role, $columnWidth, " ", STR_PAD_BOTH);
}
$totalColumns = count($dates) + 1;
// HEADINGS
printf(
implode("|", array_fill(0, $totalColumns, '%s')) . "\n",
str_pad('Roles', $columnWidth, " ", STR_PAD_BOTH),
...array_values($dates)
);
// SEPARATOR
echo implode("|", array_fill(0, $totalColumns, str_repeat('=', $columnWidth)));
// DATA
foreach ($roles as $role => $paddedRole) {
echo "\n$paddedRole";
foreach ($nested as $date => $roleGroup) {
echo '|' . str_pad(implode(', ', $nested[$date][$role] ?? ['-']), $columnWidth, " ", STR_PAD_BOTH);
}
}
输出:
Roles | 01/02/14 | 08/02/14 | 15/02/14
====================|====================|====================|====================
Leader | Jerry | Baz, Gaz, Haz | -
Musician | Bob | Charles | -
Singer | Carol | Norman | -
Astronaut | - | - | Neil