我很难找到最好的办法。我在mysql中有三个表,这与健身房应用程序构建有关,一个用于肌肉锻炼,一个用于有氧运动,另一个用于容纳用户每天锻炼的结果。每天锻炼的基础是0到1次有氧运动和0 - 但是私人教练决定进行多次肌肉锻炼。在锻炼结束时,用户将每个锻炼的结果放入表格并提交。结果只是一个文本字段。我有一个数据库,为每个包含
的结果创建一行username,exercise type (muscle,cardio),exercise name, exercise result, date
所以一个例子是
John,muscle,bench press, 225lb max out, 2012-08-21
John,cardio,rowing,12 miles, 2012-08-21
然后我想获取此信息并按照所选日期在标准表中显示。因此,每个日期有多个用户,每个用户可以有多个答案。标题是
username,cardio, muscle 1, muscle 2 ect..
(显示当天的数量)
然后结果下降并填写表格。
除了拨打几十个选择电话之外,我正试图找到一种方法来做到这一点。我打算尝试创建一些排序或数组并使用它。有什么想法吗?
答案 0 :(得分:1)
我会选择阵列。问题在于调度肌肉/心脏结果。
要格式化HTML并获取标题,假设我们首先是有氧运动,然后是肌肉。
因此,您选择该日期的所有行,按用户名和有氧运动/肌肉进行排序。
然后:
$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;
}
现在你有类似的东西:
'John': {
'cardio': [
[ 'rowing', '12 miles' ],
[ 'running', '2 miles' ],
],
'muscle': [ ]
},
'Jack': {
'cardio': [ ],
'muscle': [ 'bench', '300lbs' ],
}
要在HTML中对此进行格式化,我们已经保存了任何用户的最大心肺数量和最大肌肉数量。因此,1 + MaxC + MaxM列的表将保留所有用户,订购:
Name Cardio 1 Cardio 2 Muscle 1
John Rowing Running -
12 miles 2 miles
Jack - - Bench
300lbs
建立它:
// 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>";
}
答案 1 :(得分:1)
我建议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)
您将在exercise_entry
中生成练习条目,并保留结果NULL
。这样,用户就知道存在预期的值。
在PHP方面,您只需根据过滤器参数从exercise_entry
表中获取数据。
修改1
如果练习类型和名称之间存在1:1的关系,则可以使用3表格方法。
user (username PK) exercise_name (name PK, type) exercise_entry (id PK, username FK, date, exercise_name FK, result)
答案 2 :(得分:1)
首先,可能没有必要为三类练习中的每一类都有单独的表:也许一个exercises
表就足够了,一列用于指示每个记录是肌肉锻炼还是心血管锻炼?
关于你的问题:你想要做的是 pivot 你的数据,这是MySQL开发人员本身故意不包含的功能(因为他们觉得它更适合于演示文稿) ,而不是数据库,应用程序层);其他RDBMS可能对此类操作有更多本机支持。但是,仍然可以通过分组您的数据并使用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
如果练习列表是动态的,您可以生成包含此SQL语句的字符串,然后prepare and execute来自该字符串的语句:
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;