如何在表格中水平和垂直打印数据

时间:2016-11-02 01:57:57

标签: php mysql mysqli

我正在尝试使用分配给每个用户名的用户名和数据创建表。 我有项目,每个项目内都有几个流程。所以我想要打印带有用户名和项目显示的表,然后将每个进程分配给用户名。像这样:

username|    project TMNT    |  project LEON  |  project MAT  | 
--------+--------------------+----------------+---------------+
barikan | ANM BLD, BGD CUP   | N/A            |       N/A     |
beny    | N/A                | N/A            |       BGD CUP |
bob     | N/A                | ANM BLD        |       N/A     |

ANM BLD, BGD CUP是每个项目的流程。

我能做的是将项目水平打印并垂直打印用户名:

<table class="table table-hover">
 <thead>
     <tr>
      <th>Name</th>
     <?php
    $result = getRecord();
    $count = 0;
    if (mysqli_num_rows($result) > 0)
    while($row = mysqli_fetch_array($result))
    {   
        $projectNo = $row['projectNo'];
        $title = $row['title'];
        $code = $row['code'];

        echo "<th>".$projectNo." ".$title." ".$code."</th>";
        $count++;
    }   
    ?>
    </tr>
</thead>
<tbody>
    <?php

        $result3 = getLeader();
            if (mysqli_num_rows($result3) > 0)
                while($row = mysqli_fetch_array($result3))
                {
                    $username = $row['username'];

                    echo "<tr>
                    <td>".$username."</td>";
                }       
    ?>
</tbody>

我的数据库表格如何:

用户表

uid| username| salary|  
---+---------+-------+
1  | bob     | 0     |
2  | barikan | 0     |
3  | beny    | 0     |
4  | adam    | 0     |

项目表

projectNo| title|  
---------+------+
1610004  | TMNT |
1610005  | LEON |
1610006  | MAT  |

流程表(将人员分配给流程)

projectNo| process | proc_leader|  
---------+---------+------------+
1610004  | ANM BLD | barikan    |
1610004  | BGD CUP | barikan    |
1610005  | ANM BLD | bob        |
1610006  | BGD CUP | beny       |

我知道我可以使用group_concat函数来连接同一个项目中的所有进程,但是如何相应地打印到每个项目?

我用来连接进程的SQL查询:

"SELECT proc_leader.projectNo, group_concat(proc_leader.process) AS processes, username
        FROM user
        LEFT OUTER JOIN proc_leader ON user.username=proc_leader.proc_leader
        GROUP BY username, proc_leader.projectNo";

修改

那么如果我有两张桌子呢: 流程表(将人员分配给流程)

projectNo| process | proc_leader|  
---------+---------+------------+
1610004  | ANM BLD | barikan    |
1610004  | BGD CUP | barikan    |
1610005  | ANM BLD | bob        |
1610006  | BGD CUP | beny       |

proc_checker表(其中person被分配给具有不同角色的进程)

projectNo| process | proc_checker|  
---------+---------+-------------+
1610004  | ANM BLD | adam        |
1610004  | BGD CUP | barikan     |
1610005  | ANM BLD | barikan     |
1610006  | BGD CUP | beny        |

所以在最后的结果中它应该是这样的(领导者,跳棋者):

username|    project TMNT                          |  project LEON  |  project MAT                    | 
--------+------------------------------------------+----------------+---------------------------------+
adam    | ANM BLD(chk)                             | N/A            |       N/A                       |                       |
barikan | ANM BLD(ld), BGD CUP(ld), BGD CUP(chk)   | ANM BLD(chk)   |       N/A                       |
beny    | N/A                                      | N/A            |       BGD CUP(ld), BGD CUP(chk) |
bob     | N/A                                      | ANM BLD(ld)    |       N/A                       |

ld =领导者; CHK =检查

我应该LEFT加入两个表吗?谢谢你的帮助

1 个答案:

答案 0 :(得分:1)

假设你有这样的表结构(sqlfiddle):

CREATE TABLE `user` (
  `uid` INT(11) UNSIGNED NOT NULL PRIMARY KEY,
  username VARCHAR(255) NOT NULL UNIQUE,
  salary INT(11) UNSIGNED NOT NULL DEFAULT 0
);

CREATE TABLE project (
  projectNo INT(11) UNSIGNED NOT NULL PRIMARY KEY,
  title VARCHAR(255) NOT NULL UNIQUE
);

CREATE TABLE process (
  projectNo INT(11) UNSIGNED NOT NULL,
  process VARCHAR(255) NOT NULL,
  proc_leader VARCHAR(255) NOT NULL,

  FOREIGN KEY(projectNo) REFERENCES project(projectNo),
  FOREIGN KEY(proc_leader) REFERENCES `user`(username)
);

CREATE TABLE proc_checker (
  projectNo INT(11) UNSIGNED NOT NULL,
  process VARCHAR(255) NOT NULL,
  proc_checker VARCHAR(255) NOT NULL,

  FOREIGN KEY(projectNo) REFERENCES project(projectNo),
  FOREIGN KEY(proc_checker) REFERENCES `user`(username)
);

INSERT INTO `user`(uid, username, salary)
VALUES
(1, "bob", 0),
(2, "barikan", 0),
(3, "beny", 0),
(4, "adam", 0);

INSERT INTO project(projectNo, title)
VALUES
(1610004, "TMNT"),
(1610005, "LEON"),
(1610006, "MAT");

INSERT INTO process(projectNo, process, proc_leader)
VALUES
(1610004, "ANM BLD", "barikan"),
(1610004, "BGD CUP", "barikan"),
(1610005, "ANM BLD", "bob"),
(1610006, "BGD CUP", "beny");

INSERT INTO proc_checker(projectNo, process, proc_checker)
VALUES
(1610004, "ANM BLD", "adam"),
(1610004, "BGD CUP", "barikan"),
(1610005, "ANM BLD", "barikan"),
(1610006, "BGD CUP", "beny");

带有一些纪念的结果片段如下:

<?php
// root root :)
$conn = mysqli_connect('127.0.0.1', 'root', 'root', 'test3');

// 1.Get data
// data for final table
// format is [username][projectNo] => [process1, process2, ..., processN]
$result = [];
// map project no to its title
$projectNoToTitle = [];
$sql = '
    SELECT uid, username
    FROM `user`
    ORDER BY username
';
$query = mysqli_query($conn, $sql);
// for each user
while ($data = mysqli_fetch_assoc($query)) {
    $sql = '
        SELECT a.* FROM
        (
            (
              -- select pairs project - leader
              SELECT p.projectNo, p.title, CONCAT(pr.process, "(ld)") AS process
              FROM project p
                LEFT JOIN process pr ON p.projectNo = pr.projectNo
                  AND pr.proc_leader = "' . mysqli_real_escape_string($conn, $data['username']) . '"
            )
            -- union all means we union result of queries, which have structure
            -- and don\'t remove duplicates (it\'s faster than UNION and 
            -- more logical because in our sittuation it won\'t be any duplicates) 
            UNION ALL 
            (
              -- select pairs project - checker
              SELECT p.projectNo, p.title, CONCAT(pch.process, "(chk)") AS process
              FROM project p
                LEFT JOIN proc_checker pch ON p.projectNo = pch.projectNo
                  AND pch.proc_checker = "' . mysqli_real_escape_string($conn, $data['username']) . '"  
            )
        ) AS a
        ORDER BY a.projectNo
    ';
    $query2 = mysqli_query($conn, $sql);
    // for each project => process pair of user
    while ($data2 = mysqli_fetch_assoc($query2)) {
        $username = $data['username'];
        $projectNo = $data2['projectNo'];
        $projectTitle = $data2['title'];
        $process = $data2['process'];

        $projectNoToTitle[$projectNo] = $projectTitle;

        if (!isset($result[$username])) {
            $result[$username] = [];
        }
        if (!isset($result[$username][$projectNo])) {
            $result[$username][$projectNo] = [];
        }
        if ($process) {
            $result[$username][$projectNo][] = $process;
        }
    }
}
// \1.Get data

// 2. Output table
// create table header
// it's columns should contain all projects
if ($result) {
    $header =
        '<th>username</th>' .
        array_reduce(array_values($projectNoToTitle), function ($p, $n) {
            return $p . '<th>project ' . htmlspecialchars($n) . '</th>';
        });

    // output body
    $body = '';
    foreach ($result as $username => $usernameData) {
        $row = '<td>' . htmlspecialchars($username) . '</td>';
        foreach ($projectNoToTitle as $projectNo => $projectTitle) {
            $r = (isset($usernameData[$projectNo]) && $usernameData[$projectNo])
                ? implode(', ', $usernameData[$projectNo])
                : 'N/A';
            $row .= '<td>' . htmlspecialchars($r) . '</td>';
        }
        $body .= "<tr>$row</tr>";
    }
    echo "<table><thead>$header</thead><tbody>$body</tbody></table>";
}
// \2. Output table

如果发现了一些错误,请随意修改:)