1

以下のようなMySQLカテゴリテーブルがあります。どのparentフィールドIDが親カテゴリを示し、hassubフィールドがカテゴリにサブカテゴリがあるかどうかを示します。(私はPHPをベースとして使用しています。)

************************************
| ID  | parent  | name   | hassub  |
************************************
| 1   | 0       | Nature | 1       |
| 2   | 1       | foo    | 0       |
| 3   | 1       | bar    | 1       |
| 4   | 3       | bar1   | 0       |
| 5   | 0       | Anime  | 0       |
************************************

すべてのカテゴリを階層形式で取得するには、できるだけ少ない MySQL クエリでこれを行う方法はありますか?

  • メインカテゴリー1
    • サブカテゴリー1
    • サブカテゴリー2
    • サブカテゴリー3
  • メインカテゴリー2
  • メインカテゴリー3
    • サブカテゴリー1
    • サブカテゴリー2

私が今していることは、すべての行をparent = 0取得してから、それぞれの行を照会してサブカテゴリを取得することです。

4

3 に答える 3

3

これはテキスト エディタで手書きしたものです... 便利な開発環境を持っていないので、これが単に間違っているか、タイプミスが含まれている場合はお詫びします。

しかし、とにかく、アイデアは明確で健全だと思います。

は次の$sqlようになります。

SELECT 
    parent.id as parentid,
    parent.[name] as parentname,
    child.[name] as childname

FROM
    category child

    left join category parent -- Can't exclude parents with no children, else they won't appear in the list!
    on child.parent = parent.id

ORDER BY
    parentid

そして、PHPは次のよ​​うになります。

function categoryLevels(){
    $bullet = "*"; // You can specify your HTML/CSS :-)
    $indent = "   "; // You can specify your HTML/CSS :-)

    $sql = "_as above_";
    $query = mysql_query($sql);
    $lastParentId = 0;
    while($row = mysql_fetch_array($query)){
        $parentId = $row['parentid']
        if ($parentId != 0) {
            if ($parentId != $lastParentId) {
                echo $bullet . $row['parentname']
                $lastParentId = $parentId;
            }
            if (!is_null($row['childname']) { // this line is psuedo-code! - don't know the php equiv for is_null, sorry.
                echo $indent . $bullet . $row['childname'];
            }
        }
    }
}

これの要点は基本的に次のとおりです。

  1. すべてのカテゴリ (親を持たないものを除く) の結果セットを取得し、それらが属する親でソートします
  2. その結果セットを反復し、親の変更ごとに、親の名前を含む「ヘッダー」を出力します。
  3. 子を出力します。

これを編集して、複雑さを軽減 (および高速化) しました。IF現在、SQLは、PHPのステートメントで親行を除外するのではなく、単純に親行を完全に除外しています。

于 2013-03-22T13:59:13.237 に答える
0

データを結合できます (移動する深さがわかっている場合)。

例えば:

CREATE TABLE`test` (
  `id` INT(11) unsigned NOT NULL AUTO_INCREMENT,
  `parent` INT(10) unsigned NOT NULL DEFAULT '0',
  `name` VARCHAR(50),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO test (id, parent, name) values
(1, 0, 'Nature'),
(2, 1, 'Foo'),
(3, 1, 'Bar'),
(4, 3, 'Bar1'),
(5, 0, 'Anime');

2 つのレベルがあることがわかっているため、必要な結合は 1 つだけです。レベルごとに結合が必要であり、これは隣接リスト モデルの多くの欠点の 1 つです。

SELECT a.name AS 'Level 1', b.name AS 'Level 2' FROM test AS a
LEFT JOIN test AS b
  ON b.parent = a.id
WHERE a.parent = 0

これにより、次の出力が得られます。

+---------+---------+
| LEVEL 1 | LEVEL 2 |
---------------------
|  Nature |     Foo |
|  Nature |     Bar |
|   Anime |  (null) |
+---------+---------+

この出力から、配列をトラバースして、箇条書きリストに入力できます。

于 2013-03-22T13:51:23.670 に答える