如何高效创建视图统计64张同结构表的指定条件行数?
嘿,手动写64个UNION来创建视图简直是噩梦——不仅费时间,后期维护(比如加表、改表名)也超级麻烦。给你几个更高效的方案,按需选择:
几乎所有关系型数据库都有存储元数据的系统表,我们可以用它来自动拼接出需要的UNION语句,不用手动敲每个表。
举个MySQL的例子(不同数据库的系统表名会有差异,比如PostgreSQL用pg_tables,SQL Server用sys.tables):
假设你的表名是tableName1、tableName2...对应France、UK...,如果表名和国家的对应没有直接规律,可以先建个简单的映射表table_country_map,存好table_name和country的对应关系:
CREATE TABLE table_country_map ( table_name VARCHAR(100) PRIMARY KEY, country VARCHAR(50) NOT NULL ); -- 批量插入64条映射数据,比如: INSERT INTO table_country_map VALUES ('tableName1', 'France'), ('tableName2', 'UK'), ...;
然后用下面的SQL生成所有查询片段:
SELECT CONCAT( 'SELECT ''', country, ''' as country, count(RC) as complete FROM ', table_name, ' WHERE RC=18' ) AS query_line FROM table_country_map;
把查询结果里的所有query_line用UNION ALL连接起来(注意用UNION ALL代替UNION,因为不会有重复数据,性能更高),最后加上CREATE VIEW globalResults AS 前缀,就是完整的视图创建语句了。
如果需要定期更新视图(比如新增表后),可以写个存储过程自动完成拼接和创建:
还是以SQL Server为例:
CREATE PROCEDURE RefreshGlobalResultsView AS BEGIN SET NOCOUNT ON; DECLARE @fullSql NVARCHAR(MAX) = ''; -- 拼接所有查询片段 SELECT @fullSql += CONCAT( 'SELECT ''', country, ''' as country, count(RC) as complete FROM ', table_name, ' WHERE RC=18 UNION ALL ' ) FROM table_country_map; -- 移除最后多余的"UNION ALL " SET @fullSql = LEFT(@fullSql, LEN(@fullSql) - 10); -- 创建或替换视图 SET @fullSql = 'CREATE OR ALTER VIEW globalResults AS ' + @fullSql; -- 执行生成的SQL EXEC sp_executesql @fullSql; END;
以后只要执行EXEC RefreshGlobalResultsView;,就能自动更新视图,不用再手动改SQL了。
既然64张表结构完全一致,只是按国家拆分,长远来看,把它们合并成一张分区表是最好的选择。按country字段分区后,统计查询会变得无比简单:
SELECT country, COUNT(RC) AS complete FROM unified_partitioned_table WHERE RC=18 GROUP BY country;
不仅查询效率更高,数据维护(比如备份、新增国家)也会轻松很多。当然这个需要调整现有数据结构,适合有时间做重构的场景。
最后提醒一句:一定要用UNION ALL代替UNION,前者不会做去重检查,性能比后者好太多,而你的场景里每个国家的结果都是唯一的,完全不需要去重。
内容的提问来源于stack exchange,提问作者Petr Beneš

