ThinkPHP5 possède une méthode de partition intégrée, qui peut être utilisée pour implémenter des partitions de table simples. Lorsque vous ajoutez, modifiez, supprimez ou interrogez une seule donnée, vous pouvez facilement utiliser la méthode de partition, car ces opérations ont une caractéristique commune, à savoir que vous pouvez savoir clairement à l'avance quel enregistrement vous souhaitez utiliser. Mais il existe un besoin que ThinkPHP5 ne semble pas résoudre. Par exemple, lorsqu'une grande table est divisée en plusieurs sous-tables, comment obtenir des données de pagination en fonction de conditions et d'un tri pertinents.
Dans ce scénario de demande, puisque nous ne savons pas à l'avance quelles données apparaîtront sur la première page et quelles données apparaîtront sur la deuxième page, comment interroger les données de la liste qui correspondent dynamiquement en fonction du conditions de recherche ?
Une tentative ratée
La première et la plus directe manière qui me vient à l'esprit est de combiner la méthode de partition et la méthode de pagination. Cela semble logique. Le résultat a été tragique. , et la base de données s'est écrasée directement. La raison en est que pour implémenter une requête de pagination, la méthode de partition doit réunir plusieurs sous-tables, et les sous-tables de chaque union sont sous la forme de select *, ce qui affectera sérieusement l'efficacité de la requête. lors de l'obtention d'enregistrements Lors du calcul du nombre total, il n'est absolument pas nécessaire d'interroger tous les champs.
La voie du succès
Puisque select * affectera l'efficacité, que se passera-t-il si la clé primaire est sélectionnée ? Bien sûr, c'est assez rapide ! L'idée générale est d'obtenir les données en deux étapes. La première fois consiste à interroger la clé primaire, puis la deuxième fois consiste à obtenir les données correspondantes basées sur la clé primaire. La mise en œuvre spécifique est la suivante :
Idée de base
Après la division horizontale du tableau, lorsque les données doivent être obtenues en pages, l'efficacité deviendra très faible, le plus les sous-tables sont divisées, l'impact sur les performances des requêtes sera plus grand. L'idée principale est donc d'essayer d'obtenir l'enregistrement de données correspondant via l'identifiant de clé primaire, c'est-à-dire d'obtenir les données de la liste en deux fois.
1. Interrogez d'abord le nombre total d'enregistrements et l'identifiant de la clé primaire
Dans cette étape, dans l'instruction select de la sous-table union, il vous suffit de lister l'identifiant de la clé primaire et autres champs obligatoires supplémentaires. Les champs pertinents ne doivent pas nécessairement être présents.
2. Interrogez les données complètes correspondantes en fonction de l'identifiant de la clé primaire.
Encapsulation de fonction
1. Construisez une instruction de sous-requête SQL pour obtenir le nombre total d'enregistrements et l'ID de clé primaire
/** * 构造获取总记录数及主键ID的sql子查询语句 * @param $table 主表名称 * @param $idKey 主键id字段名称 * @param string $fields 其它字段名称,多个字段用英文逗号分隔 * @param int $num 子表数量 * @param string $where 查询条件 * @return array */ function buildPartitionSql($table,$idKey,$fields='',$num=1,$where='') { $countTable = []; $listTable = []; $fieldList = [$idKey]; if ($fields) { $fieldList = array_merge($fieldList,explode(',',$fields)); $fieldList = array_unique($fieldList); } $fieldStr = implode(',',$fieldList); for ($i = 0; $i < $num; $i++) { $countTable[] = sprintf('SELECT %s FROM %s_%s where 1=1 %s', $idKey, $table, ($i + 1), $where); $listTable[] = sprintf('SELECT %s FROM %s_%s where 1=1 %s', $fieldStr,$table, ($i + 1), $where); } $countTable = '( ' . implode(" UNION ", $countTable) . ') AS ' . $table; $listTable = '( ' . implode(" UNION ", $listTable) . ') AS ' . $table; $tables = ['countSql' => $countTable, 'listSql' => $listTable]; return $tables; }
Méthode d'appel :
Supposons que le résultat de l'exécution de la fonction buildPartitionSql est $tables, alors l'instruction SQL complète est la suivante :
Obtenez le SQL complet du nombre total d'enregistrements :
select count(1) as total from .$tables['countSql']
Obtenez le SQL complet de l'identifiant de clé primaire :
select * from .$tables['listSql']. limit 0,10
2. Construisez une instruction de sous-requête SQL pour obtenir l'enregistrement correspondant à l'identifiant spécifié
/** * 构造获取指定id对应记录的sql子查询语句 * @param $table 主表名称 * @param $idKey 指定的id字段名称 * @param $idValues 指定的id字段值 * @param int $num 子表数量 * @return string */ function buildPartitionListSql($table,$idKey,$idValues,$num=1) { $sql = ''; $ids = is_array($idValues) ? implode(',',$idValues) : $idValues; if ($ids) { $listTable = []; for ($i = 0; $i < $num; $i++) { $listTable[] = sprintf('SELECT * FROM %s_%s where %s in (%s)', $table, ($i + 1), $idKey, $ids); } $sql = '( ' . implode(" UNION ", $listTable) . ') AS ' . $table; } return $sql; }
Méthode d'appel :
En supposant que le résultat de l'exécution de la fonction buildPartitionListSql est $sql, alors l'instruction SQL complète est la suivante :
select * from .$sql
Remarque : toutes les conditions de recherche au niveau métier sont placées dans la clause union de la première étape. deuxième étape, il vous suffit d'obtenir les données basées sur l'ID.
Site Web chinois php, un grand nombre de tutoriels d'introduction thinkphp gratuits, bienvenue pour apprendre en ligne !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!