0

次のネストされたクエリを最適化するために何かを少し検索しましたwhile()が、残念ながら私の場合には適応できません。

次のデータベース関係を想像してみましょう:

ITEM 0,5---1,n ITEM_TAG 1,n---0,n TAG

ITEM (id, name, ...)
ITEM_TAG (id_item, id_tag)
TAG (id, name, ...)

ここで、タグ付きのすべての ITEM を取得したいと考えています (5 つに制限されています)。

私がやったことは、最適化する必要がある醜い次のことです:

$req=mysql_query("SELECT id, name FROM ITEM WHERE 1 ORDER BY id DESC");
while($res=mysql_fetch_array($req))
{
  $items.="<h1>".$res['name']."</h1>";
  $req_tag=mysql_query("SELECT id, name 
                        FROM TAG, ITEM_TAG
                        WHERE ITEM_TAG.id_item='".$res['id']."'
                        AND ITEM_TAG.id_tag=TAG.id
                        LIMIT 5");
  while($res_tag=mysql_fetch_array($req_tag))
  $items.="&bull; ".$res_tag['name']."<br/>";
}

別の方法として、すべてのアイテムとそのタグを選択し、次のように配列でフィルター処理することもできます。

$req=mysql_query("SELECT ITEM.id AS 'item_id',
                         ITEM.name AS 'item_name',
                         TAG.id AS 'tag_id',
                         TAG.name AS 'tag_name'
                         FROM ITEM, ITEM_TAG, TAG
                         WHERE ITEM_TAG.id_item=ITEM.id
                         AND ITEM_TAG.id_tag=TAG.id
                         ORDER BY ITEM.id DESC");
  while($res=mysql_fetch_array($req))
  {
    $listTag[$res['item_id']][$res['tag_id']]=$res['tag_name'];
    $listItem[$res['item_id']]=$res['item_name'];
  }
  foreach($listItem as $item_id=>$item_name)
  {
    $items.="<h1>".$val."</h1>";
    foreach($listTag[$id_item] $tag_id=>$tag_name)
    $items.="&bull; ".$tag_name."<br/>";
  }

より良く、より速く、より軽く(そしてダフトパンクほど強くない;))それを行うためのアイデアやアドバイスはありますか?

いくつかLEFT JOINRIGHT JOINまたはtag1、tag2... tag5フィールドをITEMテーブルに入れますか、それとも他ですか? ただし、ITEM には 0 ~ 5 個の TAG が関連付けられている可能性があることに注意してください...

4

1 に答える 1

1

コメントするには長くなりすぎたので、ここに投稿します。

出力前に DB の結果を PHP にキャッシュすることについて話すとき、私はいつも少し躊躇します。なぜなら、それは * data * base と PHP の関係について「直感的」ではないからです。

この場合、特にITEMテーブルが非常に大きい場合は、出力する前に大量の文字列を PHP にキャッシュすることになります。

したがって、現在のロジックを使用して、準備済みステートメントを利用できると思います。

$req=$mysqli->query("SELECT id, name FROM ITEM WHERE 1 ORDER BY id DESC");
$tag=$mysqli->prepare("SELECT id, name FROM tag, item_tag WHERE item_tag.id_item=? AND item_tag.id_tag=tag.id LIMIT 5");
$tag->bind_param("i",$tid);
while($res=$req->fetch_assoc())
{
  echo "<h1>".$res['name']."</h1>";
  $tid=intval($res["id"]);
  $tag->execute();
  $req_tag=$tag->get_result();
  while($res_tag=$req_tag->fetch_assoc())
  {
    echo "&bull; ".$res_tag['name']."<br/>";
  }
}

上記のコードはテストされていませんが、アイデアは得られると思います。

于 2013-02-19T04:58:39.563 に答える