sql >> データベース >  >> RDS >> Mysql

PHPの入れ子関数を使用して、選択したカテゴリからサブカテゴリを選択するにはどうすればよいですか?

    いくつかの解決策があります。まず、次のデータ(categories)を使用します 表)例として。

    +----+--------------------------+-----------+
    | id | name                     | parent_id |
    +----+--------------------------+-----------+
    |  1 | Electronics              |      NULL |
    |  2 | Apparel & Clothing       |      NULL |
    |  3 | Phones & Accessories     |         1 |
    |  4 | Computer & Office        |         1 |
    |  5 | Men's Clothing           |         2 |
    |  6 | Women's Clothing         |         2 |
    |  7 | Cell Phones              |         3 |
    |  8 | Cell Phone Accessories   |         3 |
    |  9 | Phone Parts              |         3 |
    | 10 | Computers & Accessories  |         4 |
    | 11 | Tablets & Accessories    |         4 |
    | 12 | Computer Peripherals     |         4 |
    | 13 | Computer Components      |         4 |
    | 14 | Office Electronics       |         4 |
    +----+--------------------------+-----------+
    

    ソリューション1(隣接リスト ):

    WITH(一般的なテーブル式) 句(MySQL 8.0が必要):

    // Database connection
    
    $options = [
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ];
    
    $pdo = new PDO('mysql:host=localhost;dbname=<DATABASE_NAME>', '<USERNAME>', '<PASSWORD>', $options);
    
    function getCategories(PDO $db, $parentId = null)
    {
        $sql = $parentId ? 'WITH RECURSIVE cte (id, name, parent_id) AS (SELECT id, name, parent_id FROM categories WHERE parent_id = ? UNION ALL SELECT c.id, c.name, c.parent_id FROM categories c INNER JOIN cte ON c.parent_id = cte.id) SELECT * FROM cte' : 'SELECT * FROM categories';
        $stmt = $db->prepare($sql);
        $stmt->execute($parentId ? [$parentId] : null);
        return $stmt->fetchAll();
    }
    

    MySQL 5.7を使用している場合は、その機能を次のように変更します。

    function getCategories(PDO $db, $parentId = null)
    {
        $sql = $parentId ? 'SELECT id, name, parent_id FROM (SELECT * FROM categories ORDER BY parent_id, id) c, (select @pv := ?) initialisation WHERE find_in_set(parent_id, @pv) AND LENGTH(@pv := concat(@pv, ",", id))' : 'SELECT * FROM categories';
        $stmt = $db->prepare($sql);
        $stmt->execute($parentId ? [$parentId] : null);
        return $stmt->fetchAll();
    }
    

    データベース内のすべてのカテゴリを取得するには:

    $allCategories = getCategories($pdo);
    

    出力:

    +----+--------------------------+-----------+
    | id | name                     | parent_id |
    +----+--------------------------+-----------+
    |  1 | Electronics              |      NULL |
    |  2 | Apparel & Clothing       |      NULL |
    |  3 | Phones & Accessories     |         1 |
    |  4 | Computer & Office        |         1 |
    |  5 | Men's Clothing           |         2 |
    |  6 | Women's Clothing         |         2 |
    |  7 | Cell Phones              |         3 |
    |  8 | Cell Phone Accessories   |         3 |
    |  9 | Phone Parts              |         3 |
    | 10 | Computers & Accessories  |         4 |
    | 11 | Tablets & Accessories    |         4 |
    | 12 | Computer Peripherals     |         4 |
    | 13 | Computer Components      |         4 |
    | 14 | Office Electronics       |         4 |
    +----+--------------------------+-----------+
    

    カテゴリのサブカテゴリを取得するには:

    $subCategories = getCategories($pdo, 1); // 1 is parent_id
    

    出力:

    +----+--------------------------+-----------+
    | id | name                     | parent_id |
    +----+--------------------------+-----------+
    |  3 | Phones & Accessories     |         1 |
    |  4 | Computer & Office        |         1 |
    |  7 | Cell Phones              |         3 |
    |  8 | Cell Phone Accessories   |         3 |
    |  9 | Phone Parts              |         3 |
    | 10 | Computers & Accessories  |         4 |
    | 11 | Tablets & Accessories    |         4 |
    | 12 | Computer Peripherals     |         4 |
    | 13 | Computer Components      |         4 |
    | 14 | Office Electronics       |         4 |
    +----+--------------------------+-----------+
    

    HTML出力が必要な場合は、$allCategoriesをループできます。 / $subCategories (あなたの例に基づく):

    function prepareCategories(array $categories)
    {
        $result = [
            'all_categories' => [],
            'parent_categories' => []
        ];
        foreach ($categories as $category) {
            $result['all_categories'][$category['id']] = $category;
            $result['parent_categories'][$category['parent_id']][] = $category['id'];
        }
        return $result;
    }
    
    function buildCategories($categories, $parentId = null)
    {
        if (!isset($categories['parent_categories'][$parentId])) {
            return '';
        }
    
        $html = '<ul>';
        foreach ($categories['parent_categories'][$parentId] as $cat_id) {
            if (isset($categories['parent_categories'][$cat_id])) {
                $html .= "<li><a href='#'>{$categories['all_categories'][$cat_id]['name']}</a>";
                $html .= buildCategories($categories, $cat_id);
                $html .= '</li>';
            } else {
                $html .= "<li><a href='#'>{$categories['all_categories'][$cat_id]['name']}</a></li>";
            }
        }
        $html .= '</ul>';
    
        return $html;
    }
    
    echo buildCategories(prepareCategories($allCategories));
    

    出力:

    echo buildCategories(prepareCategories($subCategories), 1);
    

    出力:

    ソリューション2(入れ子集合 ):

    left列を追加します およびright 私たちのテーブルに、親に属するグループを識別する番号を入れます。 (parent_idは使用しないことに注意してください 列。)

    +----+--------------------------+--------------------------+
    | id | name                     | parent_id | left | right |
    +----+--------------------------+--------------------------+
    |  1 | Electronics              |      NULL |    1 |    22 |
    |  2 | Apparel & Clothing       |      NULL |   23 |    28 |
    |  3 | Phones & Accessories     |         1 |    2 |     9 |
    |  4 | Computer & Office        |         1 |   10 |    21 |
    |  5 | Men's Clothing           |         2 |   24 |    25 |
    |  6 | Women's Clothing         |         2 |   26 |    27 |
    |  7 | Cell Phones              |         3 |    3 |     4 |
    |  8 | Cell Phone Accessories   |         3 |    5 |     6 |
    |  9 | Phone Parts              |         3 |    7 |     8 |
    | 10 | Computers & Accessories  |         4 |   11 |    12 |
    | 11 | Tablets & Accessories    |         4 |   13 |    14 |
    | 12 | Computer Peripherals     |         4 |   15 |    16 |
    | 13 | Computer Components      |         4 |   17 |    18 |
    | 14 | Office Electronics       |         4 |   19 |    20 |
    +----+--------------------------+--------------------------+
    

    次に、関数を変更する必要があります:

    function getCategories(PDO $db, $parentId = null)
    {
        $sql = $parentId ? 'SELECT children.* FROM categories parent INNER JOIN categories children ON parent.left < children.left AND parent.right > children.left WHERE parent.id = ?' : 'SELECT * FROM categories';
        $stmt = $db->prepare($sql);
        $stmt->execute($parentId ? [$parentId] : null);
        return $stmt->fetchAll();
    }
    

    データベース内のすべてのカテゴリを取得するには:

    $allCategories = getCategories($pdo);
    

    出力:

    +----+--------------------------+--------------------------+
    | id | name                     | parent_id | left | right |
    +----+--------------------------+--------------------------+
    |  1 | Electronics              |      NULL |    1 |    22 |
    |  2 | Apparel & Clothing       |      NULL |   23 |    28 |
    |  3 | Phones & Accessories     |         1 |    2 |     9 |
    |  4 | Computer & Office        |         1 |   10 |    21 |
    |  5 | Men's Clothing           |         2 |   24 |    25 |
    |  6 | Women's Clothing         |         2 |   26 |    27 |
    |  7 | Cell Phones              |         3 |    3 |     4 |
    |  8 | Cell Phone Accessories   |         3 |    5 |     6 |
    |  9 | Phone Parts              |         3 |    7 |     8 |
    | 10 | Computers & Accessories  |         4 |   11 |    12 |
    | 11 | Tablets & Accessories    |         4 |   13 |    14 |
    | 12 | Computer Peripherals     |         4 |   15 |    16 |
    | 13 | Computer Components      |         4 |   17 |    18 |
    | 14 | Office Electronics       |         4 |   19 |    20 |
    +----+--------------------------+--------------------------+
    

    カテゴリのサブカテゴリを取得するには:

    $subCategories = getCategories($pdo, 1); // 1 is parent_id
    

    出力:

    +----+--------------------------+--------------------------+
    | id | name                     | parent_id | left | right |
    +----+--------------------------+--------------------------+
    |  3 | Phones & Accessories     |         1 |    2 |     9 |
    |  4 | Computer & Office        |         1 |   10 |    21 |
    |  7 | Cell Phones              |         3 |    3 |     4 |
    |  8 | Cell Phone Accessories   |         3 |    5 |     6 |
    |  9 | Phone Parts              |         3 |    7 |     8 |
    | 10 | Computers & Accessories  |         4 |   11 |    12 |
    | 11 | Tablets & Accessories    |         4 |   13 |    14 |
    | 12 | Computer Peripherals     |         4 |   15 |    16 |
    | 13 | Computer Components      |         4 |   17 |    18 |
    | 14 | Office Electronics       |         4 |   19 |    20 |
    +----+--------------------------+--------------------------+
    

    ソリューション1に示すようにHTMLをレンダリングできます 。 続きを読む 入れ子集合モデルの更新と新しいデータの挿入について。

    ソースと読み取り:




    1. SQL Server(T-SQL)でログインのデフォルト言語を取得する2つの方法

    2. 文の最後の単語:SQLの場合(正規表現は可能ですか?)

    3. SQL Server(T-SQL)でデータベースメールを有効にする

    4. SQLCMDを使用したSQLデータベース保守タスクの実行