我想从数据库中获取数据并相应地水平和垂直打印。我有一个项目表,每个项目中可以有多个进程。对于每个流程,都有一些指定人员。 所以我所做的是首先获得有关项目的信息:
// 1.Get data
// data for final table
$result = [];
// map project no to its title
$projectNoToTitle = [];
$sql = '
SELECT projectNo, code, title
FROM `project`
ORDER BY projectNo
';
$query = mysqli_query($conn, $sql);
然后,对于每个项目,我尝试获取进程并计算每个user_type中的人数:
// for each process
while ($data = mysqli_fetch_assoc($query)) {
$sql2 = '
SELECT projectNo, process, GROUP_CONCAT(col separator "+") as `count`
FROM
(
SELECT projectNo, process, concat(count(*),"(",user_type,")") as `col`
FROM
(
(
SELECT * FROM proc_leader t1
LEFT JOIN
(
SELECT username, user_type FROM user GROUP BY username
) t2 ON t1.proc_leader = t2.username GROUP BY t1.proc_leader
)
UNION
(
SELECT * FROM proc_checker t1
LEFT JOIN
(
SELECT username, user_type FROM user GROUP BY username
) t2 ON t1.proc_checker = t2.username GROUP BY t1.proc_checker
)
UNION
(
SELECT * FROM proc_staff t1
LEFT JOIN
(
SELECT username, user_type FROM user GROUP BY username
) t2 ON t1.proc_staff = t2.username GROUP BY t1.proc_staff
)
) AS a GROUP BY projectNo, process, user_type
) t GROUP BY projectNo, process
';
$query2 = mysqli_query($conn, $sql2);
// for each project => process pair of user
while ($data2 = mysqli_fetch_assoc($query2)) {
$projectN = $data['projectNo'];
$code = $data['code'];
$title = $data['title'];
$projectNo = $data2['projectNo'];
$process = $data2['process'];
$count = $data2['count'];
$projectNoToTitle[$projectNo] = $process;
if (!isset($result[$title])) {
$result[$title] = [ 'code' => $code, 'projects' => []];
}
if (!isset($result[$title]['projects'][$projectNo])) {
$result[$title]['projects'][$projectNo] = [];
}
if ($count) {
$result[$title]['projects'][$projectNo][] = $count;
}
}
}
然后我试着打印我的桌子:
<table>
<?php
// 2. Output table
// create table header
// it's columns should contain all processes
if ($result)
{
$header =
'<th>Code</th>
<th>Title</th>' .
array_reduce(array_values($projectNoToTitle), function ($p, $n) {
return $p . '<th>Process ' . htmlspecialchars($n) . '</th>';
});
// output body
$body = '';
foreach ($result as $title => $titleData)
{
$row = '<td>' . htmlspecialchars($titleData['code']) . '</td>' . '<td>' . htmlspecialchars($title) . '</td>';
foreach ($projectNoToTitle as $projectNo => $projectTitle)
{
$r = isset($titleData['projects'][$projectNo])
? implode(', ', $titleData['projects'][$projectNo])
: 'N/A';
$row .= '<td>' . htmlspecialchars($r) . '</td>';
}
$body .= "<tr>$row</tr>";
}
echo "<thead>$header</thead><tbody>$body</tbody>";
}// \2. Output table
?>
</table>
我的预期输出是:
| projectNo | code | title | Process ANM BGR | Process BLD COL |Process BGA CDP |
+-----------+------+-----------+-----------------+-----------------+----------------+
| 170001 | pr1 | Project1 | 1(FT)+1(CT) | 1(AP) | |
| 170002 | pr2 | Project2 | | | 1(CT) |
但我得到了:
| projectNo | code | title | Process BGD COL | Process BGA CDP |
+-----------+------+-----------+---------------------------+---------------------------+
| 170001 | pr1 | Project1 | 1(CT)+1(FT), 1(AP) | 1(CT) |
| 170002 | pr2 | Project2 | 1(CT)+1(FT), 1(AP) | 1(CT) |
如何将每个流程安排为列?谢谢
project
表的表格:
project table:
| projectNo | code | title |
+-----------+------+----------+
| 170001 | pr1 | Project1 |
| 170002 | pr2 | Project2 |
process table:
| projectNo | process |
+-----------+---------+
| 170001 | ANM BGR |
| 170001 | BGD COL |
| 170002 | BGA CDP |
username table:
| uid | username | user_type|
+-----+------------+----------+
| 1 | AARONJAMES | CT |
| 2 | ADELINE | AP |
| 3 | AARONKOH | CT |
| 4 | AHMAD | FT |
proc_leader table:
| projectNo | process | proc_leader|
+-----------+---------+------------+
| 170001 | ANM BGR | AARONJAMES |
| 170001 | BGD COL | ADELINE |
| 170002 | BGA CDP | AARONKOH |
proc_checker table:
| projectNo | process | proc_checker |
+-----------+---------+--------------+
| 170001 | ANM BGR | AARONJAMES |
| 170001 | BGD COL | AARONJAMES |
| 170002 | BGA CDP | AARONKOH |
proc_staff table:
| projectNo | process | proc_staff |
+-----------+---------+------------+
| 170001 | ANM BGR | AHMAD |
更新后的答案是:
因此,您可以看到重复的过程。但我需要它在1列以下。 像那样:
| projectNo | code | title | Process ANM BGR | Process BLD COL |Process BGA CDP |
+-----------+------+-----------+-----------------+-----------------+----------------+
| 170001 | pr1 | Project1 | 1(FT)+1(CT) | 1(AP) | |
| 170002 | pr2 | Project2 | 2(CT) | | 1(CT) |
答案 0 :(得分:2)
从我看到的是,当从不同的表中获取数据时,你在while循环中执行while循环,我认为在这种情况下很难跟踪和合并它们。 所以我建议,首先从你的项目表中获取所有数据并做好准备。
e.g。
/** start for getting projects **/
$query = 'SELECT projectNo, code, title
FROM `project`
ORDER BY projectNo';
$res = $con->query($query);
$projects = [];
while ($data = $res->fetch_assoc()) {
$projects[] = $data;
}
/** end for getting projects **/
然后执行另一个查询以获取来自不同表的数据并执行while循环。 因此,一旦获得所需的所有数据,当您在html上执行表格时,可以轻松地将它们合并。
检查我的工作代码:
/** start for getting projects **/
$query = 'SELECT projectNo, code, title
FROM `project`
ORDER BY projectNo';
$res = $con->query($query);
$projects = [];
while ($data = $res->fetch_assoc()) {
$projects[] = $data;
}
/** end for getting projects **/
$titles = array();
$query = 'SELECT projectNo, process, GROUP_CONCAT(col separator "+") as `count`
FROM
(
SELECT projectNo, process, concat(count(*),"(",user_type,")") as `col`
FROM
(
(
SELECT * FROM proc_leader t1
LEFT JOIN
(
SELECT username, user_type FROM user GROUP BY username
) t2 ON t1.proc_leader = t2.username GROUP BY t1.proc_leader
)
UNION
(
SELECT * FROM proc_checker t1
LEFT JOIN
(
SELECT username, user_type FROM user GROUP BY username
) t2 ON t1.proc_checker = t2.username GROUP BY t1.proc_checker
)
UNION
(
SELECT * FROM proc_staff t1
LEFT JOIN
(
SELECT username, user_type FROM user GROUP BY username
) t2 ON t1.proc_staff = t2.username GROUP BY t1.proc_staff
)
) AS a GROUP BY projectNo, process, user_type
) AS t GROUP BY projectNo, process';
$res = $con->query($query);
/** process the data first and store to variables and arrays **/
while ($data = $res->fetch_assoc()) {
$projectNo = $data['projectNo'];
$processName = $data['process'];
$titles[] = $processName;
$count = $data['count'];
if (!isset($allProcess[$projectNo]))
$allProcess[$projectNo] = [];
if ($count)
$allProcess[$projectNo][$processName] = $count;
}
?>
<style>
table, th, td {
border: 1px solid #000;
}
</style>
<table>
<?php
/** now do the printing of data **/
if ($allProcess) {
$header =
'<th>ProjectNo</th>
<th>Code</th>
<th>Title</th>' .
array_reduce(array_values($titles), function ($p, $n) {
return $p . '<th>Process ' . htmlspecialchars($n) . '</th>';
});
$body = '';
/** loop through projects first instead **/
foreach ($projects as $p) {
$body .= '<tr>';
$body .= '<td>' . htmlspecialchars($p['projectNo']) . '</td>' . '<td>' . htmlspecialchars($p['code']) . '</td>' . '<td>' . htmlspecialchars($p['title']) . '</td>';
/** loop through titles or all process **/
foreach ($titles as $t) {
$row = $allProcess[$p['projectNo']]; // e.g. Array ( [process] => Array ( [170001]...
$r = isset($row) && isset($row[$t]) ? $row[$t] : 'N/A';
$body .= '<td>' . htmlspecialchars($r) . '</td>';
}
$body .= '</tr>';
}
echo "<thead>$header</thead><tbody>$body</tbody>";
}
?>
</table>
虽然上面的代码仍然可以改进,但这应该会给你一个快速启动。
<强>更新强>
关于获取相同的两列,您可以添加$titles = array_unique($titles);
以删除重复的列。你把它放在while ($data = $res->fetch_assoc()) {
块之后。
/** process the data first and store to variables and arrays **/
$rows = [];
while ($data = $res->fetch_assoc()) {
$rows[] = $data;
$projectNo = $data['projectNo'];
$processName = $data['process'];
$titles[] = $processName;
$count = $data['count'];
if (!isset($allProcess[$projectNo]))
$allProcess[$projectNo] = [];
if ($count)
$allProcess[$projectNo][$processName] = $count;
}
$titles = array_unique($titles); // the fix
答案 1 :(得分:0)
试试这个:
while ($data2 = mysqli_fetch_assoc($query2)) {
$projectN = $data['projectNo'];
$code = $data['code'];
$title = $data['title'];
$projectNo = $data2['projectNo'];
$process = $data2['process'];
$count = $data2['count'];
// Here instead of overwriting, save process names in an array
if (!isset($projectNoToTitle[$projectNo])) {
$projectNoToTitle[$projectNo] = [];
}
$projectNoToTitle[$projectNo][] = $process;
if (!isset($result[$title])) {
$result[$title] = [ 'code' => $code, 'projects' => []];
}
if (!isset($result[$title]['projects'][$projectNo])) {
$result[$title]['projects'][$projectNo] = [];
}
if ($count) {
$result[$title]['projects'][$projectNo][] = $count;
}
}
然后在格式化代码中,你需要改变一些事情:
$header =
'<th>Code</th>
<th>Title</th>' .
array_reduce(array_values($projectNoToTitle), function ($p, $n) {
// now $n is an array so implode it
$header = '';
foreach ($n as $p) {
$header .= '<th>Process ' . htmlspecialchars($n)) . '</th>'
}
return $p . $header;
});
// output body
$body = '';
foreach ($result as $title => $titleData)
{
$row = '<td>' . htmlspecialchars($titleData['code']) . '</td>' . '<td>' . htmlspecialchars($title) . '</td>';
foreach ($projectNoToTitle as $projectNo => $projectTitle)
{
$r = isset($titleData['projects'][$projectNo])
// again, this is a brutal hack, you may rewrite part of
// the code to do the same thing if you like.
? implode('</td><td>', $titleData['projects'][$projectNo])
: 'N/A';
$row .= '<td>' . htmlspecialchars($r) . '</td>';
}
$body .= "<tr>$row</tr>";
}
echo "<thead>$header</thead><tbody>$body</tbody>";
请注意,如果每个项目都没有相同的流程,那么这不会起作用,但也许你明白了。你的问题无论如何都不清楚,因为你没有提供一个包含更多进程的样本表,所以我无法知道你想要做什么。
无论如何,问题是你每次都要覆盖进程名称。希望它有所帮助!