表格中的水平数据分配

时间:2017-02-28 07:25:59

标签: mysql

所以我有两张桌子:

project.sql
projectNo| title |
---------+-------+
17020002 | test  |
17020003 | test2 |

process.sql
projectNo| process | studio  |
---------+---------+---------+
17020002 | ANM     | STELLAR |
17020002 | BLD     |         |
17020003 | ANM KEY | APEX    |
17020003 | BLD     | PALETTE |

我想要做的是创建mysql查询,它将工作室名称水平显示为表格的标题,并将“x”放在匹配的位置:

所以我希望表格看起来像这样:

| title         | APEX | BASECAMP | CANVAS | HORIZON | LAUNCHPAD | NEBULA | ORBIT | PALETTE | SANDBOX | STELLAR | THE CLIMB | TOONIGAMI | TREEHOUSE |
+---------------+------+----------+--------+---------+-----------+--------+-------+---------+---------+---------+-----------+-----------+-----------+
| Project test  |      |          |        |         |           |        |       |         |         |         |           |           |           |
| ANM           |      |          |        |         |           |        |       |         |         | x       |           |           |           |
| BLD           |      |          |        |         |           |        |       |         |         |         |           |           |           |
| Project test2 |      |          |        |         |           |        |       |         |         |         |           |           |           |
| ANM KEY       | x    |          |        |         |           |        |       |         |         |         |           |           |           | 
| BLD           |      |          |        |         |           |        |       | x       |         |         |           |           |           |  

我试图使用的查询:

SELECT proc.projectNo, proc.title, 
    max(case when studio = "APEX" then "x" else "" end) as APEX,
    max(case when studio = "BASECAMP" then "x" else "" end) as BASECAMP,
    max(case when studio = "CANVAS" then "x" else "" end) as CANVAS,
    max(case when studio = "HORIZON" then "x" else "" end) as HORIZON,
    max(case when studio = "LAUNCHPAD" then "x" else "" end) as LAUNCHPAD,
    max(case when studio = "NEBULA" then "x" else "" end) as NEBULA,
    max(case when studio = "ORBIT" then "x" else "" end) as ORBIT,
    max(case when studio = "PALETTE" then "x" else "" end) as PALETTE,
    max(case when studio = "SANDBOX" then "x" else "" end) as SANDBOX,
    max(case when studio = "STELLAR" then "x" else "" end) as STELLAR,
    max(case when studio = "THE CLIMB" then "x" else "" end) as THECLIMB,
    max(case when studio = "TOONIGAMI" then "x" else "" end) as TOONIGAMI,
    max(case when studio = "TREEHOUSE" then "x" else "" end) as TREEHOUSE
    FROM process p1
    LEFT JOIN
    (
        SELECT projectNo, title
        FROM 
        (
            SELECT projectNo, CONCAT('Project ', title) as title, 0 AS a FROM project
            UNION ALL
            SELECT projectNo, process, 1 AS a FROM process
        ) t
        ORDER BY projectNo, a, title
    )proc
    ON p1.projectNo = proc.projectNo
    GROUP BY proc.projectNO, proc.title

通过使用此查询,我得到了:

| title         | APEX | BASECAMP | CANVAS | HORIZON | LAUNCHPAD | NEBULA | ORBIT | PALETTE | SANDBOX | STELLAR | THE CLIMB | TOONIGAMI | TREEHOUSE |
+---------------+------+----------+--------+---------+-----------+--------+-------+---------+---------+---------+-----------+-----------+-----------+
| ANM           |      |          |        |         |           |        |       |         |         | x       |           |           |           |
| BLD           |      |          |        |         |           |        |       |         |         | x       |           |           |           |
| Project test  |      |          |        |         |           |        |       |         |         | x       |           |           |           |
| ANM KEY       | x    |          |        |         |           |        |       | x       |         |         |           |           |           |
| BLD           | x    |          |        |         |           |        |       | x       |         |         |           |           |           | 
| Project test2 | x    |          |        |         |           |        |       | x       |         |         |           |           |           |  

如何达到我想要的效果?谢谢你的帮助

2 个答案:

答案 0 :(得分:0)

你应该使用左连接
如果您需要两个级别,那么您可以使用

select * from from (
  SELECT 
          0 as level,
          pj.projectNo as projectNo, 
          CONCAT('Project ', pj.title) as title, 
          null as APEX,
          null as BASECAMP,
          null as CANVAS,
          null as HORIZON,
          null as LAUNCHPAD,
          null as NEBULA,
          null as ORBIT,
          null as PALETTE,
          null as SANDBOX,
          null as STELLAR,
          null as THECLIMB,
          null as TOONIGAMI,
          null as TREEHOUSE
    FROM project as pj

  UNION ALL 
  SELECT 
          max(1), 
          pj.projectNo, 
          pc.process,
          max(case when pc.studio = "APEX" then "x" else "" end) ,
          max(case when pc.studio = "BASECAMP" then "x" else "" end), 
          max(case when pc.studio = "CANVAS" then "x" else "" end) ,
          max(case when pc.studio = "HORIZON" then "x" else "" end) ,
          max(case when pc.studio = "LAUNCHPAD" then "x" else "" end) ,
          max(case when pc.studio = "NEBULA" then "x" else "" end) ,
          max(case when pc.studio = "ORBIT" then "x" else "" end) ,
          max(case when pc.studio = "PALETTE" then "x" else "" end),
          max(case when pc.studio = "SANDBOX" then "x" else "" end) ,
          max(case when pc.studio = "STELLAR" then "x" else "" end) ,
          max(case when pc.studio = "THE CLIMB" then "x" else "" end),
          max(case when pc.studio = "TOONIGAMI" then "x" else "" end) ,
          max(case when pc.studio = "TREEHOUSE" then "x" else "" end) 
    FROM project as pj
    left join process  as  pc on pj.projectNo = pc.projectNo
    GROUP BY pj.projectNO, pj.title ) t
    order by t.level, t.projectNo, t.title

答案 1 :(得分:0)

我找到了另一种方法:

/** start for getting titles**/
$sql = '
        SELECT proj_title, CONCAT(projectNo, " ", proj_title) AS title
        FROM (
            SELECT projectNo, CONCAT("Project ", title) AS proj_title, 0 AS a FROM project p1
            UNION ALL
            SELECT DISTINCT projectNo, process, 1 AS a FROM process p2) t
        ORDER BY projectNo, a, title
        ';
$projects = [];
$query = mysqli_query($conn, $sql);
// for each title
while ($data = mysqli_fetch_assoc($query)) 
{
    $projects[] = $data;
    $titles = array();
    $sql2 = '         
            SELECT a.* FROM
            (
                (
                  SELECT upr.projectNo, upr.process, p.stdid, p.studio_name, COALESCE(upr.num_appearences, 0) AS count
                  FROM studios p
                    LEFT JOIN
                    (
                        SELECT CONCAT(upr.projectNo, " ", upr.process) AS process, projectNo, studio, COUNT(DISTINCT studio) AS num_appearences
                        FROM process upr
                        GROUP BY projectNo, process, studio   
                    )upr ON p.studio_name = upr.studio
                    AND upr.process = "' . mysqli_real_escape_string($conn, $data['title']) . '"
                )
            ) AS a
            ORDER BY a.projectNo, a.studio_name, a.process';
    $rows = []; 
    $query2 = mysqli_query($conn, $sql2);
    while ($data2 = mysqli_fetch_assoc($query2)) {
        $rows[] = $data2;
        $projectNo = $data['title'];
        $studioName = $data2['studio_name'];
        $titles[] = $studioName;
        $count = $data2['count'];

        if (!isset($allProcess[$projectNo])) 
            $allProcess[$projectNo] = [];

        if ($count) 
            $allProcess[$projectNo][$studioName] = $count;      
    }
    $titles = array_unique($titles); 
}

表格:

<table class="paginated" style=" margin-right:10%;">
<?php
/** now do the printing of data **/
if ($allProcess)
{
    $header =
        '<th>Title</th>' .
        array_reduce(array_values($titles), function ($p, $n) {
            return $p . '<th>Studio ' . htmlspecialchars($n) . '</th>';
        });

    $body = '';
    /** loop through projects first instead **/
    foreach ($projects as $p) {
        $body .= '<tr>';
        $body .= '<td>' . htmlspecialchars($p['proj_title']) . '</td>';

        /** loop through titles or all process **/
        foreach ($titles as $t) {
            $row = $allProcess[$p['title']]; // e.g. Array ( [process] => Array ( [170001]...
            $r = isset($row) && isset($row[$t]) ? $row[$t] : ' ';
            $body .= '<td>' . htmlspecialchars($r) . '</td>';
        }
        $body .= '</tr>';
    }
    echo "<thead>$header</thead><tbody>$body</tbody>";
}
?>    
</table>