1

重複の可能性:
MySQLのツリー構造テーブルを単一のクエリで任意の深さまでクエリすることは可能ですか?

phpを使用してmysqlデータベースからデータを取得し、結果をテーブルに表示する管理領域を作成しました。基本的に、親カテゴリ、その下の最初のサブカテゴリ、次に3番目のレベルのサブカテゴリ/サブジェクトが表示されます。

それは完全に機能しますが、私はmysqlとphpに慣れていないので、テーブルを構築するときに3つのwhileループを使用し、各ループでmysqlクエリを作成するので、dbリソースを節約するためにコードを改善する必要があると確信しています確かにそれを行うには間違った方法です。

誰かがこれを行うための最良の方法について私にいくつかの援助を提供できますか?

コードは次のとおりです。

           $query = mysql_query("SELECT * FROM categories WHERE
parent_id is null
order by cat_id asc;", $hd)
or die ("Unable to run query");       

while ($row = mysql_fetch_assoc($query)) {
echo '<tr style="font-weight:bold;color:green;"><td>'. $row    ['cat_id'].'</td><td>'.$row['cat_name'].'</td><td>'.$row    ['parent_id'].'</td><td>'.$row['active'].'</td><td>'.$row    ['url'].'</td><td>'.$row['date_updated'].'</td></tr>' ;

$query2 = mysql_query("SELECT * FROM categories WHERE
                (active = 'true' AND parent_id = ".$row    ['cat_id'].")
                order by cat_id asc;", $hd)
      or die ("Unable to run query");
while ($row2 = mysql_fetch_assoc($query2)) {
echo '<tr style="font-weight:bold;"><td>'. $row2['cat_id'].'</td><td>'.$row2    ['cat_name'].'</td><td>'.$row2['parent_id'].'</td><td>'.$row2    ['active'].'</td><td>'.$row2['url'].'</td><td>'.$row2    ['date_updated'].'</td></tr>' ;
    $query3 = mysql_query("SELECT * FROM categories WHERE
                (active = 'true' AND parent_id = ".$row2    ['cat_id'].")
                order by cat_id asc;", $hd)
      or die ("Unable to run query");
      while ($row3 = mysql_fetch_assoc($query3)) {
echo '<tr><td>'. $row3['cat_id'].'</td><td>'.$row3['cat_name'].'</td><td>'.$row3    ['parent_id'].'</td><td>'.$row3['active'].'</td><td>'.$row3    ['url'].'</td><td>'.$row3['date_updated'].'</td></tr>' ;

}
}
}

編集

さて、私は少し調査をしました、そしてこれは私がいるところです:

おそらく小さなデータベースの場合、私のアプローチは問題ありません。

配列を使用してデータを格納する大規模なデータベースの場合、おそらく、メモリを大量に消費する可能性のある再帰的アプローチを使用する必要があることを意味します。人々の意見を聞きたいのですが、ネストされたwhileループでdbクエリをループするよりも優れていますか?

私は次のスレッドを見つけました。ここでは、再帰なしで1つのクエリだけでこれを行うための答えがあります。現在のデザインに位置列を追加する必要があるかどうかわからない: PHPとmysqlを使用して無制限のレベルのメニューを作成する方法

隣接モデルの代わりに入れ子集合モデルを使用して設計を再構築すると、mysqlクエリは必要な順序で結果を返しますが、入れ子集合設計を維持することは私の頭上にあり、やり過ぎだと思います。

それでおしまい。誰かがその上に何か入力がある場合は、会話に追加してください。この種の要件は大量のWebアプリケーションに必要であるため、勝利のアプローチが必要です。

4

2 に答える 2

1

私はあなたがこのようなことをすることができると思います:

SELECT * FROM categories
WHERE active = 'true'
ORDER BY parent_id, cat_id

これにより、すべてのカテゴリがparent_id、次にcat_idの順に表示されます。次に、結果セットを取得し、そこから多次元配列を作成します。次に、カテゴリを出力するために、現在行っているのと同じようにこの配列をループできます。

これはDBアクセスの観点からは優れていますが、この大きなアレイをメモリに保持する必要があるため、より多くのメモリを消費します。したがって、これは実際に考慮する必要のあるトレードオフです。

于 2012-11-29T19:43:31.520 に答える
0

修正すべき点はたくさんありますが、クエリの削減に関する質問に答えるだけです。WHERE句をすべてまとめて削除し、whileループ内でifステートメントを使用することをお勧めします。外部変数を使用して特定の条件に一致するすべての結果を保持し、ループの後にそれらすべてを一度にエコーします。このようなもの(簡潔にするために、あなたのものを変数に入れます)

//before loop
$firstInfoSet = '';
$secondInfoSet = '';
$thirdInfoSet = '';

//in while loop

if($parentID == NULL)
{
  $firstInfoSet.= $yourFirstLineOfHtml;
}

if($active && $parentID == $catID) // good for query 2 and 3 as they are identical
{
  $secondInfoSet.= $yourSecondLineOfHtml;
  $thirdInfoSet.= $yourThirdLineOfHtml;
}

//after loop
echo $firstInfoSet . $secondInfoSet . $thirdInfoSet;

これで、必要な種類のグループ化を作成し、必要に応じて簡単に変更して、必要な場所に結果を配置できます。

-編集-質問をよりよく理解した後...

$query = mysql_query("SELECT * FROM categories order by cat_id asc;", $hd);
$while ($row = mysql_fetch_assoc($query)){
   if($row['parent_id'] == NULL){
      //echo out your desired html from your first query 
   }
   if($row['active'] && $row['parent_id']== $row['cat_id']){
      //echo out your desired html from your 2nd and 3rd queries
   }
}
于 2012-11-29T20:21:34.083 に答える