请求编写适配动态新增表的SQL查询,汇总TOTAL_VALUE列数据
解决方案:动态计算符合命名规则表的TOTAL_VALUE总和
嘿,针对你需要汇总database_01库中所有tb_data_年份_月份格式(2011-2018全月份+未来新增同格式表)的TOTAL_VALUE列总和的需求,我整理了两种适配PHP触发场景的实现方式:
方式一:PHP中动态生成SQL语句
这种方式直接在PHP脚本里搞定表名筛选和SQL拼接,适合轻量、快速落地的场景。
步骤1:筛选符合规则的表名
先从数据库的系统表中捞取所有符合命名格式的表:
<?php $dbHost = '你的数据库主机'; $dbUser = '你的数据库用户名'; $dbPass = '你的数据库密码'; $dbName = 'database_01'; // 建立数据库连接 $conn = new mysqli($dbHost, $dbUser, $dbPass, $dbName); if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } // 查询符合规则的表:匹配tb_data_YYYY_MM,年份从2011开始(自动包含未来新增的) $tableQuery = " SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '$dbName' AND TABLE_NAME REGEXP '^tb_data_[0-9]{4}_[0-9]{2}$' AND CAST(SUBSTRING(TABLE_NAME, 9, 4) AS UNSIGNED) >= 2011 "; $result = $conn->query($tableQuery); $tables = []; if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { $tables[] = $row['TABLE_NAME']; } }
步骤2:拼接求和SQL并执行
拿到表名后,拼接UNION ALL语句汇总每个表的总和,再计算最终总数值:
if (!empty($tables)) { // 逐个拼接每个表的求和语句 $unionParts = []; foreach ($tables as $table) { $unionParts[] = "SELECT SUM(TOTAL_VALUE) AS table_sum FROM `$table`"; } $sumSql = "SELECT SUM(table_sum) AS total_total_value FROM (" . implode(" UNION ALL ", $unionParts) . ") AS temp_sum"; // 执行查询并获取结果 $sumResult = $conn->query($sumSql); if ($sumResult->num_rows > 0) { $total = $sumResult->fetch_assoc()['total_total_value']; echo "所有符合条件表的TOTAL_VALUE总和为: " . $total; } else { echo "未查询到有效数据"; } } else { echo "没有找到符合命名规则的表"; } // 关闭连接 $conn->close(); ?>
方式二:MySQL存储过程+PHP调用
如果想把逻辑放在数据库端(方便复用或复杂场景),可以创建存储过程,PHP只需要调用即可:
步骤1:创建存储过程
在MySQL中执行以下语句创建存储过程:
DELIMITER // CREATE PROCEDURE CalculateTotalValueSum() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE tableName VARCHAR(255); -- 定义游标获取符合规则的表名 DECLARE cur CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'database_01' AND TABLE_NAME REGEXP '^tb_data_[0-9]{4}_[0-9]{2}$' AND CAST(SUBSTRING(TABLE_NAME, 9, 4) AS UNSIGNED) >= 2011; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; SET @sumSql = ''; OPEN cur; read_loop: LOOP FETCH cur INTO tableName; IF done THEN LEAVE read_loop; END IF; -- 拼接UNION ALL语句 IF @sumSql = '' THEN SET @sumSql = CONCAT("SELECT SUM(TOTAL_VALUE) AS table_sum FROM `", tableName, "`"); ELSE SET @sumSql = CONCAT(@sumSql, " UNION ALL SELECT SUM(TOTAL_VALUE) AS table_sum FROM `", tableName, "`"); END IF; END LOOP; CLOSE cur; -- 执行最终求和查询 IF @sumSql != '' THEN SET @sumSql = CONCAT("SELECT SUM(table_sum) AS total_total_value FROM (", @sumSql, ") AS temp_sum"); PREPARE stmt FROM @sumSql; EXECUTE stmt; DEALLOCATE PREPARE stmt; ELSE SELECT 0 AS total_total_value; -- 无符合表时返回0 END IF; END // DELIMITER ;
步骤2:PHP调用存储过程
<?php $dbHost = '你的数据库主机'; $dbUser = '你的数据库用户名'; $dbPass = '你的数据库密码'; $dbName = 'database_01'; $conn = new mysqli($dbHost, $dbUser, $dbPass, $dbName); if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } // 调用存储过程获取总和 $result = $conn->query("CALL CalculateTotalValueSum()"); if ($result->num_rows > 0) { $total = $result->fetch_assoc()['total_total_value']; echo "所有符合条件表的TOTAL_VALUE总和为: " . $total; } else { echo "未查询到有效数据"; } $conn->close(); ?>
关键注意点
- 确保数据库账号拥有
INFORMATION_SCHEMA.TABLES的查询权限,以及所有目标表的SELECT权限。 - 正则表达式
^tb_data_[0-9]{4}_[0-9]{2}$严格匹配命名格式,避免误抓其他相似表。 - 两种方式都会自动包含未来新增的符合规则的表,无需修改代码适配新表。
内容的提问来源于stack exchange,提问作者user9560017
相关产品推荐
相关产品推荐

