1

何かを行う最善の方法を見つけるのに苦労しています。私は mysql に 3 つのテーブルを持っています。これはビルド中のジム アプリに関係しています。毎日、パーソナル トレーナーが決定した 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..(その日の数だけ表示します)、結果が下に下がり、表に記入されます。

何十もの選択呼び出しを行うことは別として、私はこれを行う方法を見つけようとしています。何らかのソートまたは配列を作成して使用することを考えています。何か案は?

4

3 に答える 3

1

まず、運動の 3 つのカテゴリごとに個別の表を用意する必要はないかもしれません。おそらく、exercises各記録が筋肉運動であるか有酸素運動であるかを示す列があれば、1 つの表で十分ではないでしょうか?

あなたの質問に: あなたがしようとしているのは、データをピボットすることです。これは、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 ステートメントを含む文字列を生成し、その文字列からステートメントを準備して実行できます。

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;
于 2012-08-21T18:26:06.473 に答える
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>";
 }
于 2012-08-21T18:15:45.117 に答える
1

3NF セットアップには 4 つのテーブルをお勧めします。

ユーザー (ユーザー名 PK)
運動タイプ (タイプ PK)
エクササイズ名(PK名)
エクササイズ_エントリ (ID PK、ユーザー名 FK、日付、エクササイズタイプ FK、エクササイズ名 FK、結果)

で演習エントリを生成しexercise_entry、結果を残しNULLます。このようにして、ユーザーは期待される値があることを認識します。

exercise_entryPHP 側では、フィルター パラメーターに基づいてテーブルからデータを取得するだけです。

編集 1

運動の種類と名前の間に 1 対 1 の関係がある場合は、3 テーブルのアプローチが有効です。

ユーザー (ユーザー名 PK)
エクササイズ名(名前PK、タイプ)
運動エントリ (id PK、ユーザー名 FK、日付、運動名 FK、結果)
于 2012-08-21T18:16:33.200 に答える