0

これは私の用語テーブル(カテゴリ)のデータベース構造です:

   id   |   name   |   parent_id   |   level   |   position   
--------------------------------------------------------------
   1    |   term 1 |   NULL        |   0       |   1
   2    |   term 2 |   1           |   1       |   1
   3    |   term 3 |   1           |   1       |   2
   4    |   term 4 |   NULL        |   0       |   2
   5    |   term 5 |   4           |   1       |   1

したがって、用語2と3は1の第1レベルの子であり、5は4の第1レベルの子です。

これは私の質問です:(そしてそれは正しくありません、これは修正されるべきです)

SELECT
    `id`,
    `name`
FROM
    `terms`
ORDER BY
    `position` ASC,
    `level` ASC

これは私のphpです:

$terms = array();

// query part

if(!$this->_db->resultRows > 0)
  return $terms;

while($d = $this->_db->fetch($r))
{
  $terms[$d->id] = new Term($d->id);
}     

return $terms;

現在の結果:

term 1
  term 2
  term 5
term 4
 term 3

しかし、結果は次のようになります。

term 1
  term 2
  term 3
term 4
  term 5

正しい結果を得るためにクエリを変更する方法がわかりません。
目標は、これを(複数の)選択ボックス
に出力することです。ネストされたリストでそれを行う方法は知っていますが、選択をネストすることはできません。

4

1 に答える 1

0

さて、この種の問題に対処する方法はたくさんあります。これから紹介するすべての方法で、表にレベル列が必要というわけではありません。私の意見では、他の列にある情報から推測できるため、冗長なデータです。

最大「レベル」が 1 (最大深度は 2) になることがわかっている場合は、次のようなクエリを使用できます。

SELECT
        t.`id`,
        t.`name`,
        IF(p.`position` IS NULL, t.`position`*{$row_count}, p.`position`*{$row_count}+t.`position`) AS display_order
FROM
        `terms` t
        LEFT JOIN `terms` p ON p.`id` = t.`parent_id`
ORDER BY
        display_order

$row_count計算されます:

SELECT COUNT(*) FROM `terms`

この SQL を変更して、より多くのレベル (深さ) で機能するようにする方法はありますが、サポートする最大レベル/深さごとにクエリを大きくする必要があります。


レベル数が不明な場合は、おそらく次のようにする必要があります。

$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$sth = $dbh->prepare('SELECT id,name FROM terms WHERE parent_id IS NULL ORDER BY position');
$sth->execute(array(NULL));
$terms = $sth->fetchAll();

$sql = 'SELECT id,name FROM terms WHERE parent_id = ? ORDER BY position';
$terms_to_check = $terms;
$terms = array();
while(count($terms_to_check))
{
        $k = array_shift($terms_to_check);
        $terms[] = $k;
        $sth = $dbh->prepare($sql);
        $sth->execute(array($k['id']));
        $results = $sth->fetchAll();
        $terms_to_check = array_merge($results, $terms_to_check);
}

(ちなみに、PDO を使用することをお勧めします。)

于 2012-06-29T20:32:12.723 に答える