简体   繁体   English

需要将来自多个MySql表的信息组合到html表中的diaply

[英]Need to combine info from multiple MySql tables to diaply in html table

I am having difficulty finding the one best way to do something. 我很难找到最好的办法。 I have three tables in mysql, this has to do with a gym app im building, one is for muscle exercises, one is for cardio exercises, the other is to house users results from each workout daily. 我在mysql中有三个表,这与健身房应用程序构建有关,一个用于肌肉锻炼,一个用于有氧运动,另一个用于容纳用户每天锻炼的结果。 Every day a workout is created based on 0 to 1 cardio exercises and 0 - however many muscle exercises the personal trainer decided. 每天锻炼的基础是0到1次有氧运动和0 - 但是私人教练决定进行多次肌肉锻炼。 At the end of the workout the user puts their results for each exercise into a form and submits it. 在锻炼结束时,用户将每个锻炼的结果放入表格并提交。 results are just a text field. 结果只是一个文本字段。 I have a database that creates a row for every individual result that consists of 我有一个数据库,为每个包含的结果创建一行

username,exercise type (muscle,cardio),exercise name, exercise result, date

so an example would be 所以一个例子就是

John,muscle,bench press, 225lb max out, 2012-08-21
John,cardio,rowing,12 miles, 2012-08-21

I then want to take this info and display it in a standard table per the date chosen. 然后,我想要获取此信息并按照所选日期在标准表中显示。 So there are multiple users per date and each user can have multiple answers. 因此,每个日期有多个用户,每个用户可以有多个答案。 The headers would be 标题是

username,cardio, muscle 1, muscle 2 ect.. ( shows as many as their are for that day ) then the results going down and filling in the table. username,cardio, muscle 1, muscle 2 ect.. (显示当天的数量)然后结果下降并填写表格。

Aside from making dozens of select calls I am trying to figure out a way to do this. 除了进行几十个选择调用之外,我试图找到一种方法来做到这一点。 I am going thinking of trying to create some sort or array and use that. 我打算尝试创建一些排序或数组并使用它。 Any ideas? 有任何想法吗?

I'd go with the array. 我会选择阵列。 The problem is in dispatching the muscle/cardio results. 问题在于调度肌肉/心脏结果。

To format in HTML and get the headers, let's say we have first the cardio, then the muscle. 要格式化HTML并获得标题,假设我们首先是有氧运动,然后是肌肉运动。

So you SELECT all rows of that date, ordering by username and cardio/muscle. 因此,您选择该日期的所有行,按用户名和有氧运动/肌肉进行排序。

Then: 然后:

$users = array();
$maxes = array('cardio' => 0, 'muscle' => 0);

foreach($row = ...)
{
    list($user, $com, $name, $result) = $row;
    if (!isset($users[$user]))
        $userData = array('cardio' => array(), 'muscle' => array());
    else
        $userData = $users[$user];
    $userData[$com][] = array($name, $result);
    if (count($userData[$com]) > $maxes[$com])
        $maxes[$com] = count($userData[$com]);
    $users[$user] = $userData;
}

Now you have something like: 现在你有类似的东西:

'John': {
     'cardio': [
        [ 'rowing', '12 miles' ],
        [ 'running', '2 miles' ],
     ],
     'muscle': [ ]
},
'Jack': {
     'cardio': [ ],
     'muscle': [ 'bench', '300lbs' ],
}

To format this in HTML, we have saved the maximum number of cardio of any user, and the maximum number of muscle. 要在HTML中格式化,我们已经保存了任何用户的最大心肺数量和最大肌肉数量。 So a table of 1 + MaxC + MaxM columns will hold all users, ordered: 因此,1 + MaxC + MaxM列的表将包含所有用户,订购:

Name  Cardio 1    Cardio 2   Muscle 1

John  Rowing      Running    -
      12 miles    2 miles
Jack  -           -          Bench
                             300lbs

And to build it: 并建立它:

// First the header
print "<tr>";
print "<th>Name</th>";
for ($i = 0; $i < $maxes['cardio']; $i++)
    print "<th>Cardio " . ($i+1) . "</th>";
for ($i = 0; $i < $maxes['muscle']; $i++)
    print "<th>Muscle ($i+1)</th>";
print "</tr>";

foreach($users as $user => $info)
{
    print "<tr><td>$user</td>";
    foreach(array('cardio','muscle') as $key)
    {
        $data = $info[$key];
        for ($i = 0; $i < $maxes[$key]; $i++)
        {
            print "<td>";
            if (isset($data[$i]))
            {
                list($name, $result) = $data[$i];
                print "$name<br />$result";
            }
            else print '-';
            print "</td>";  
        } 
    }
    print "</tr>";
 }

I would recommend 4 tables for a 3NF setup: 我建议4个表用于3NF设置:

user (username PK)
exercise_type (type PK)
exercise_name (name PK)
exercise_entry (id PK, username FK, date, exercise_type FK, exercise_name FK, result)

You would generate the exercise entries in exercise_entry and leave the result NULL . 你会产生锻炼条目exercise_entry和离开的结果NULL This way the user knows that there is a value expected. 这样,用户知道存在预期的值。

On the PHP side you would simply fetch the data from the exercise_entry table based on the filter parameters. 在PHP端,您只需根据过滤器参数从exercise_entry表中获取数据。

Edit 1 编辑1

If there is a 1:1 relationship between an exercise type and name, a 3 table approach would work. 如果练习类型和名称之间存在1:1的关系,则可以使用3表格方法。

user (username PK)
exercise_name (name PK, type)
exercise_entry (id PK, username FK, date, exercise_name FK, result)

Firstly, it may be unnecessary to have separate tables for each of the three categories of exercise: perhaps a single exercises table would suffice, with a column to indicate whether each record is a muscle exercise or a cardiovascular one? 首先,可能没有必要为三类运动中的每一类都有单独的表格:也许只需一个exercises表就足够了,用一列来表明每条记录是肌肉运动还是心血管运动?

On to your question: what you are seeking to do is pivot your data, which is a feature that the MySQL developers have deliberately not included natively (as they feel it is more suited to the presentation, rather than the database, layer of an application); 在你的问题:你正在试图做的是转动你的数据,这是MySQL的开发人员故意本身不包括在内(因为他们觉得这是更适合演示,而不是数据库,应用层功能); other RDBMS may have more native support for such an operation. 其他RDBMS可能对此类操作有更多本机支持。 However, it is still possible to achieve what you seek by grouping your data and aggregating the results with MySQL's GROUP_CONCAT() function: 但是,通过数据进行分组并使用MySQL的GROUP_CONCAT()函数聚合结果,仍然可以实现您所寻求的目标:

SELECT   username,
         GROUP_CONCAT(IF(exercise='bench press',result,NULL)) AS `bench press`,
         GROUP_CONCAT(IF(exercise='rowing'     ,result,NULL)) AS `rowing`,
         -- etc.
FROM     results
WHERE    date = '2012-08-21'
GROUP BY username

If the list of exercises is dynamic, you can generate a string containing this SQL statement and then prepare and execute a statement from that string: 如果练习列表是动态的,您可以生成包含此SQL语句的字符串,然后从该字符串中准备并执行语句:

SELECT CONCAT('
   SELECT   username,
', GROUP_CONCAT(
     'GROUP_CONCAT(IF(exercise=',QUOTE(name),',result,NULL))'
   ,    ' AS `',REPLACE(name,'`','``'),'`'
   )
,' FROM     results
   WHERE    date = ?
   GROUP BY username
') FROM exercises INTO @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt USING '2012-08-21';
DEALLOCATE PREPARE stmt;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM