2017-01-21 4 views
0

PHPを使用してデータベースのデータからCSVテーブルを構築したいと考えています。私は子供の得点を保持するプログラミングのアプリです。私の最初のテーブルには、子供だけを定義していますPHPを使用して3つのMySQLテーブルからCSVテーブルを効率的に構築する

┏━━━━┳━━━━━━┓ 
┃ ID ┃ name ┃ 
┡━━━━╇━━━━━━┩ 
│ 1 │ John │ 
│ 2 │ Lucy │ 
│ 3 │ Zara │ 
└────┴──────┘ 

第二には、子どもたちがポイント

┏━━━━┳━━━━━━━━━━━━┓ 
┃ ID ┃ date ┃ 
┡━━━━╇━━━━━━━━━━━━┩ 
│ 1 │ 2016-12-31 │ 
│ 2 │ 2017-01-07 │ 
│ 3 │ 2017-01-14 │ 
│ 4 │ 2017-01-21 │ 
└────┴────────────┘ 

を得ることができるイベントを、定義し、三つのeventID

でイベントにたchildIDに子を持ってどのように多くのポイントを教えて
┏━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┓ 
┃ ID ┃ eventID ┃ childID ┃ points ┃ 
┡━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━┩ 
│ 1 │  1 │  1 │  21 │ 
│ 2 │  1 │  2 │  43 │ 
│ 3 │  1 │  3 │  4 │ 
│ 4 │  2 │  1 │  8 │ 
│ 5 │  2 │  2 │  15 │ 
│ 6 │  2 │  3 │  13 │ 
│ 7 │  3 │  1 │  34 │ 
│ 8 │  3 │  2 │  40 │ 
│ 9 │  3 │  3 │  20 │ 
│ 10 │  4 │  1 │  3 │ 
│ 11 │  4 │  2 │  7 │ 
│ 12 │  4 │  3 │  9 │ 
└────┴─────────┴─────────┴────────┘ 

Cの子イベントとEイベントがあるので、テーブルポイントにはC * Eの行があるとします。また<行することができ

 event;John;Lucy;Zara;⋯ 
2016-12-31; 21; 43; 4; 
2017-01-07; 8; 15; 13; 
2017-01-14; 34; 40; 20; 
2017-01-21; 3; 7; 9; 
    ⋮     ⋱ 

- スワップ> COLを、私は子供たちよりも多くのイベントをしました:今、私はこのようなテーブルを構築するための最も効率的な方法を見つけたいです。

しかし、データベースにC回のEクエリを作成することについては気になりません。私はPHPで長いと醜いクエリを生成しようとしましたが、基本的にC回Eサブクエリを作成しました。私はまた、どのようにEのクエリだけでそれを構築するアイデアがありますが、それは1つでは可能ではありませんか?

+1

「JOIN」クエリとテーブルのピボットについて、2つのことを読む必要があります。これはかなり基本的なSQLです。 –

+0

@ O.Jonesそして、1つのクエリでのみ行うことは可能でしょうか?子供の名前を列ヘッダーにする方法がわからないからです。 –

+1

あなたは1つのクエリでそれを行うことができますが、SQL内のすべてのテーブルをピボットする場合は複雑になります。私は、 'join'クエリを通してデータを選択し、それをPHPで必要なフォーマットに解析することをお勧めします。完了したら 'fputcsv()'のようなものを使ってCSV文書を作成することができます。 –

答えて

0

MySQLでは、すべての子の名前に対して慎重に行う必要がある条件付き集計を検討してください。実現可能なものが多すぎる場合(つまり数百)、PHPを使用してSQL文字列を動的に構築することを検討してください。前述のように

SELECT e.date AS `event`, 
     SUM(CASE WHEN c.name = 'John' THEN j.points ELSE 0 END) As `John`, 
     SUM(CASE WHEN c.name = 'Lucy' THEN j.points ELSE 0 END) As `Lucy`, 
     SUM(CASE WHEN c.name = 'Zara' THEN j.points ELSE 0 END) As `Zara` 
FROM EventChildJoin j 
INNER JOIN ChildTable c 
    ON j.childID = c.ID 
INNER JOIN EventTable e 
    ON j.eventID = e.ID 
GROUP BY e.date 

、MySQLは、クロス集計/ピボットメソッドを持っていないので、あなたは、アプリケーション層でSQLを構築し、処理のためのデータベース層に渡さなければなりません。 PHPでの例を次に示します。

try { 
    $dbh = new PDO("mysql:host=$hostname;dbname=$database",$username,$password);  

    # FIRST FETCH 
    $strSQL = "SELECT DISTINCT name FROM ChildTable"; 
    $STH = $dbh->query($strSQL); 
    $STH->setFetchMode(PDO::FETCH_ASSOC); 

    $strSQL = "SELECT e.date AS `event`, ";  
    while($row = $STH->fetch()) { 
     $strSQL = $strSQL . " SUM(CASE WHEN c.name = '". row['name'] ."' " . 
          "   THEN j.points ELSE 0 END) As `". row['name'] ."`,"; 
    } 

    $strSQL = " FROM EventChildJoin j". 
       " INNER JOIN ChildTable c ". 
       "  ON j.childID = c.ID ". 
       " INNER JOIN EventTable e ". 
       "  ON j.eventID = e.ID ". 
       " GROUP BY e.date;"; 
    $strSQL = str_replace(", FROM", " FROM", strSQL) # REMOVE COMMA AFTER LAST COLUMN 

    # NEXT FETCH 
    $STH = null; 
    $STH = $dbh->query($strSQL); 
    $STH->setFetchMode(PDO::FETCH_ASSOC); 
    ...  
} 

catch(PDOException $e) { 
    echo $e->getMessage(); 
    exit; 
} 
+0

おかげさまで、私はChildTableに柔軟性を持たせたいので(私は子供を追加または削除したい、PHPコードで何も変更する必要がないので)、私は子供が10人いるので、動的にその文字列を生成します。しかしteoretically、もし私がそれらを持っていたら、 "MySQL、ChildTableからすべての列を取る"のような1つのコマンドに子供の名前を持つすべての列見出しを集計する方法はありません? –

+0

しかし、テーブルには1つの列しかありません。新しい列にピボットする*名前*値を参照しています。 SQL ServerやPostgresのような他のデータベースでも、MySQLではなく動的ピボット/クロス集計機能があります。より動的なレポート作成を行うには、PHPなどのアプリケーション層でコードを実行します。 – Parfait

+0

しかし、私は第2、第3、第4行にあなたのSQLを生成する列を意味します。動的に文字列を生成するPHPを使用せずにSQLで直接動的に生成する方法はありませんか?この行を転送するにはデータが必要なのでSUM(cname = 'Zara' THEN j.points ELSE 0 END) 'Zara'は千回と言います。 MySQLでは、結果として得られるテーブルの列を動的に生成する方がよいでしょう。それとも、あなたが書いたことですが、MySQLはできませんか? –

関連する問題