2012-05-10 11 views
1

私はSaaS用のカスタムレポートモジュールを構築しており、構築しているクエリ(MySQLとPHP)について少し助言が必要です。私はテーブルを動的に構築しており、返される各レコードはそのテーブルの1つの行になります。それは動的に多くのテーブルに参加し、それは私が参加する必要がある3つのテーブルを除いて素晴らしい作品です。複雑なレポートのために最も最適に構造化された結合クエリが必要です

他のすべての表は、1-1 LEFT JOINです。たとえば、私が従業員のテーブルを照会してdepartment_idを見つけようとしている場合、それはちょうどハンディーなdoryに加わります。

First | Last | Dept 
John | Smith | Toy Department 

この複雑なことは、これらの余分な3つのテーブルに1-many joinがあることです。この結合を行うと、2〜50行のデータをどこからでも引き出す​​ことができることを指摘することも重要です。たとえば、私は、従業員テーブルを照会し、それがこのように見える終わるだろうに/アウトテーブルクロックに参加する必要があるんだ場合:

私は右が参加しなかった場合
First | Last | Time 
John | Smith | 8:00 am 
John | Smith | 12:00 pm 
John | Smith | 1:00 pm 
John | Smith | 5:00 pm 

、最初/最後の名前は次のようになりnullが、私はまだ複数の行を持っていただろう。

レポートをプルするときに設定しているテーブルで3つの1つのテーブルのうちの1つを使用する必要があるため、同じデータセルに滞在する必要があります(これは私のコントロール外にある、それだけで起こることがあります):

<table> 
    <tr> 
     <td>John</td> 
     <td>Smith</td> 
     <td>8:00 am<br />12:00 pm<br />..... </td> 
    </tr> 
</table> 

は、私は本当に、本当に、そのセルをヒットする必要が、その後引っ張って別のクエリを実行しないようにしたいですすべてのデータを取り出します。その理由は、25 +列の何千もの行を含むレポートを実行でき、25x1000行の同じクエリを実行するためです。

は私が望んでいたことは、データが返されるときに、このような何かをした:

First | Last | Time_1 | Time_2 | Time_3 | Time_4 
John | Smith | 8:00 am | 12:00 pm | 1:00 pm | 5:00 pm 

私が持っていたいくつかの考えは、PHPでwhileループを実行して、動的にMySQLのために参加構築することですが、私その列を正しく取得するためにテーブルに参加する回数を指定する必要があるという事実の問題にぶつかります。私は技術的に行うことができます:

for($i = 1; $i < 50; ++$i) { 
    $sql_fields .= "time_clock_{$i}.time AS Time_{$i},"; 
    $joins .= "LEFT JOIN time_clock AS time_clock_{$i} ON time_clock_{$i}.employee_id = emp.id"; 
} 
$sql_fields = rtrim($sql_fields,','); 

mysql_query("SELECT emp.field_blah, emp.field_blah2, {$sql_fields} FROM employees AS emp {$joins} WHERE condition = blah"); 

私はこれは本当にMySQLのといくつかのパフォーマンスの問題を引き起こすと、すべての狂気が、私はそこに持っていると思い参加していることだけで怖いです。誰でも良い考えがありますか?私はこの時点で何かを楽しませる。

+1

あなたが望むのはピボットテーブルです.MySQLで最も簡単なことではありません。おそらくコードで一番うまくいくかもしれませんが、ここには[チュートリアル](http://www.artfulsoftware.com/infotree/queries.php#78)があります。 – Ami

+0

@Ami努力のための明確なEですが、そのようなものを消化するには遅すぎます:) – n0nag0n

答えて

1

No.

2つのクエリを作成します。一つは、すべての人を1:1の要素すべてで引き抜くことです。あなたのすべての時間を引っ張る別の。その後、PHPで時間をループさせ、人々の時間配列にそれらを詰め込みます。

+0

それは悪い考えではありません.....その後、配列の従業員IDの参照をしますか?その配列は非常に巨大になるだろうし、PHPのメモリの問題を引き起こすだろうか? – n0nag0n

+1

大量のデータがある場合は、これは非常に良い方法ではありません。1つの選択肢は、フル参加をして、同じIDを持つ人々を崩壊させることです。これにより、DBから収集されたデータは増加しますが、メモリは節約されます。あなたが本当にやりたくないのは、N + 1個のクエリを作ることです。 – Amadan

+0

以前の例のように完全なLEFT JOINをやっているのですか?あなたは同じIDの崩壊によって何を意味しますか?私はその行のすべてのデータを削除することなく、それを適切に行う方法を知りません。あなたは私にアイデアを考えさせました。元の投稿の私の編集を参照してください.... – n0nag0n

0
<?php 
    $query = mysql_query("SELECT .... FROM employees LEFT JOIN.... LEFT JOIN..."); //even include the one-many tables 
    $i = 0; 
    while($rs = mysql_fetch_array($query)) { //note I'm using array not assoc 
     // echo the 1:1 table data 
     // when I hit the 1:many field do something like this, yes $j will get reset when the pointer hits the next row....I need more time to think.... 
     $j = 1; 
     while($j) { 
      if($rs[$i + $j]['id'] == $rs[$i]['id']) { 
       echo $rs[$i + $j]['Time']; 
       ++$skip_fields; 
      } else { 
       $j = 0; 
      } 
      ++$j; 
     } 
     // then use $skip_fields to skip $j number of rows that the duplicate employee ids are on and decrement the value as the pointer moves on. 
     ++$i; 
    } 
?> 

Nevermind .....数値を使用すると、列ではなく列がヒットします。 :)

関連する問題