PHP 通过创建临时表实现更高速的IN查询

发布时间 2023-04-07 15:40:47作者: 何效名
/**
 * xmsb_fastIn 通过创建临时表实现更高速的IN查询
 * @return array
 */
function xmsb_fastIn
(
    $tb_name,               // 要执行in查询的表名
    $field_name,            // 要执行in查询的字段名
    $data_array,            // in查询的条件数据集
    $not_in = false,        // 为true时,将执行NOT IN查询
    $field_type = 'INT',    // in查询的数据集字段类型,默认为:INT
    $field_length = '11'    // in查询的数据集字段长度,默认为:11
)
{
    if(empty($tb_name) || empty($data_array))
    {
        return [];
    }
    
    // 连接数据库
    $dsn = 'mysql:host=host;dbname=dbname';
    $username = 'username';
    $passwd = 'password';
    $pdo = new PDO($dsn, $username, $passwd);
    
    // 定义临时表名
    $tmp_tb = uniqid('xmsb_', true);
    
    // 创建临时表
    $create = <<<xmsb
CREATE TEMPORARY TABLE `{$tmp_tb}` (
    `{$field_name}` {$field_type}({$field_length}) NOT NULL DEFAULT 0,
    INDEX `temp_index`(`{$field_name}`) USING BTREE
);
xmsb;
    $pdo -> exec($create);
    
    // 将数据分组进行批量插入
    $datas = array_chunk($data_array, 500);
    foreach($datas as $v)
    {
        $insert = "INSERT INTO `{$tmp_tb}` (`{$field_name}`) VALUES";
        foreach($v as $vv)
        {
            $insert .= " ({$vv}),";
        }
        $insert = trim($insert, ',');
        $pdo -> exec($insert);
    }
    
    // 生成查询语句
    if($not_in)
    {
        $sql = "SELECT t1.* FROM `{$tb_name}` t1 LEFT JOIN `{$tmp_tb}` t2 ON t1.`{$field_name}` = t2.`{$field_name}` WHERE t2.`{$field_name}` IS NULL";
    }
    else
    {
        $sql = "SELECT t1.* FROM `{$tb_name}` t1 INNER JOIN `{$tmp_tb}` t2 ON t1.`{$field_name}` = t2.`{$field_name}`";
    }
    
    // 获取查询结果并返回
    $query = $pdo -> query($sql);
    $res = [];
    while($row = $query -> fetch(PDO::FETCH_ASSOC))
    {
        $res[] = $row;
    }
    
    return $res;
}