MySQL多表关联插入:如何将Jan、Feb、Mar三表数据合并插入新表
嘿,这事儿分两种常见场景,得看你最终想要的新表结构是啥样的,我给你分别说清楚:
场景1:把三个月的数据按行追加到新表(最常用)
这种是把每个月的每一条数据都作为新表的一行,同时标记清楚所属月份。
步骤1:先创建目标新表(如果还没建的话)
假设新表叫MonthlySales,结构要包含月份标识和原表的所有字段:
CREATE TABLE MonthlySales ( month VARCHAR(3) NOT NULL, -- 存月份缩写:Jan/Feb/Mar id INT NOT NULL, price DECIMAL(10,2) NOT NULL, type VARCHAR(4) NOT NULL );
步骤2:插入所有数据
用UNION ALL把三张表的数据拼起来插入,效率比UNION高(因为不会去重,而三个月的数据本身属于不同月份,没必要去重):
INSERT INTO MonthlySales (month, id, price, type) SELECT 'Jan' AS month, id, price, type FROM Jan UNION ALL SELECT 'Feb' AS month, id, price, type FROM Feb UNION ALL SELECT 'Mar' AS month, id, price, type FROM Mar;
插完之后,新表的数据会是这样的(示例前几行):
| month | id | price | type |
|---|---|---|---|
| Jan | 1 | 10 | a001 |
| Jan | 2 | 20 | a002 |
| Feb | 4 | 33 | a004 |
| Mar | 4 | 51 | a005 |
场景2:按type横向关联,展示各月对应价格
如果想要每个type一行,同时显示一月、二月、三月的价格(没有数据的月份留空),那就得用关联查询来实现。
步骤1:创建横向结构的新表
CREATE TABLE TypeMonthlyPrice ( type VARCHAR(4) PRIMARY KEY, -- 用type做主键,确保唯一 jan_price DECIMAL(10,2), feb_price DECIMAL(10,2), mar_price DECIMAL(10,2) );
步骤2:插入关联后的数据
这里用FULL OUTER JOIN来确保所有出现过的type都被包含(不管哪个月有数据):
INSERT INTO TypeMonthlyPrice (type, jan_price, feb_price, mar_price) SELECT COALESCE(j.type, f.type, m.type) AS type, -- 取第一个非空的type作为统一标识 j.price AS jan_price, f.price AS feb_price, m.price AS mar_price FROM Jan j FULL OUTER JOIN Feb f ON j.type = f.type FULL OUTER JOIN Mar m ON COALESCE(j.type, f.type) = m.type;
如果你的数据库不支持FULL OUTER JOIN(比如MySQL),可以用LEFT JOIN+UNION来模拟:
INSERT INTO TypeMonthlyPrice (type, jan_price, feb_price, mar_price) -- 先取Jan里的所有type,关联Feb和Mar SELECT j.type, j.price, f.price, m.price FROM Jan j LEFT JOIN Feb f ON j.type = f.type LEFT JOIN Mar m ON j.type = m.type UNION -- 再取Feb里没有在Jan出现过的type SELECT f.type, j.price, f.price, m.price FROM Feb f LEFT JOIN Jan j ON f.type = j.type LEFT JOIN Mar m ON f.type = m.type WHERE j.type IS NULL UNION -- 最后取Mar里没在Jan和Feb出现过的type SELECT m.type, j.price, f.price, m.price FROM Mar m LEFT JOIN Jan j ON m.type = j.type LEFT JOIN Feb f ON m.type = f.type WHERE j.type IS NULL AND f.type IS NULL;
插完之后的结果会是:
| type | jan_price | feb_price | mar_price |
|---|---|---|---|
| a001 | 10 | 20 | 16 |
| a002 | 20 | 15 | 40 |
| a003 | 30 | 18 | NULL |
| a004 | NULL | 33 | 25 |
| a005 | NULL | NULL | 51 |
一些额外提醒
- 确保新表的字段数据类型和原表完全匹配,避免插入时出现类型转换错误;
- 如果原表中有重复的
type+id组合(同一月内),建议先去重再插入,不然可能违反约束; - 如果以后还要追加四月、五月的数据,直接单独执行
INSERT INTO ... SELECT 'Apr' ... FROM Apr就行,不用再重复拼之前的表。
内容的提问来源于stack exchange,提问作者ESpaDA
相关产品推荐
相关产品推荐

