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

階層的なcmsサイトを実装する方法は?

    これをテストするために使用したテーブル構造は次のとおりです-

    CREATE TABLE  `test`.`pages` (
        `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
        `slug` varchar(45) NOT NULL,
        `title` varchar(45) NOT NULL,
        `content` text NOT NULL,
        `parent_id` int(10) unsigned DEFAULT NULL,
        PRIMARY KEY (`id`),
        UNIQUE KEY `UQ_page_parent_id_slug` (`parent_id`,`slug`),
        CONSTRAINT `FK_page_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `pages` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    (parent_id、slug)の一意のキーに注意してください。これは、次のクエリから最高のパフォーマンスを得る上で重要です。これを50k行でテストしましたが、5つのスラッグパスで1ミリ秒未満で返されました-/cms/slug-1/slug-2/slug-3/slug-4/slug-5/

    これが私が適切なクエリを構築するために思いついたPHPコードです-

    <?php
    
    // I will assume the rest of the url has already been stripped away
    $url = '/fruits/tropical/bananas/';
    
    // lets just make sure we don't have any leading or trailing /
    $url = trim($url, '/');
    
    // now let's split the remaining string based on the /
    $aUrl = explode('/', $url);
    
    /**
    * Now let's build the query to retrieve this
    */
    
    // this array stores the values to be bound to the query at the end
    $aParams = array();
    
    $field_list = 'SELECT p1.* ';
    $tables = 'FROM pages p1 ';
    $where = "WHERE p1.parent_id IS NULL AND p1.slug = ? ";
    
    // this array stores the values to be bound to the query at the end
    $aParams[] = $aUrl[0];
    
    // if we have more than one element in our array we need to add to the query
    $count = count($aUrl);
    
    for ($i = 1; $i < $count; $i++) {
    
        // add another table to our query
        $table_alias = 'p' . ($i + 1);
        $prev_table_alias = 'p' . $i;
        $tables .= "INNER JOIN pages $table_alias ON {$prev_table_alias}.id = {$table_alias}.parent_id ";
    
        // add to where clause
        $where .= "AND {$table_alias}.slug = ? ";
        $aParams[] = $aUrl[$i];
    
        // overwrite the content of $field_list each time so we
        // only retrieve the data for the actual page requested
        $field_list = "SELECT {$table_alias}.* ";
    
    }
    
    $sql = $field_list . $tables . $where;
    
    $result = $this->db->query($sql, $aParams);
    


    1. MySQLでは、GROUP_CONCATから1024文字を超える文字を取得することは可能ですか?

    2. Postgresqlのスコア/ランクを使用したフルテキストクエリ

    3. SQLのチューニング

    4. postgresqlのクエリから最小値、中央値、最大値を取得するにはどうすればよいですか?