简体   繁体   English

MySQL多表查询并总结

[英]Query from multiple table in MySQL and sum up

I have seven tables (from XT1 to XT7) and each have the same structure as below:我有七个表(从 XT1 到 XT7),每个表的结构如下:


Date日期 m1米1 m2平方米 m3立方米
2021-06-01 2021-06-01 4 4 2 2 6 6
2021-06-02 2021-06-02 3 3 2 2 5 5
2021-06-03 2021-06-03 12 12 2 2 14 14
..... ..... .. .. .. .. .. ..

I only need m3 value from each table.我只需要每个表的 m3 值。 What I'm trying to do, is to show all m3 values in a single table and sum them up like below:我想要做的是在一个表中显示所有 m3 值并将它们总结如下:

Date日期 XT1.m3 XT1.m3 XT2.m3 XT2.m3 XT3.m3 XT3.m3 XT4.m3 XT4.m3 XT5.m3 XT5.m3 XT6.m3 XT6.m3 XT7.m3 XT7.m3 Subtotal XT1~7.m3小计 XT1~7.m3
2021-06-01 2021-06-01 6 6 7 7 8 8 6 6 7 7 8 8 8 8 50 50
2021-06-02 2021-06-02 6 6 7 7 8 8 6 6 7 7 8 8 8 8 50 50
2021-06-03 2021-06-03 6 6 7 7 8 8 6 6 7 7 8 8 8 8 50 50
Total全部的 18 18 21 21 24 24 18 18 21 21 24 24 24 24 150 150

What I have tried before:我之前尝试过的:

select (TX1.m3+TX2.m3+TX3.m3...) AS subtotal, date_format(date, '%Y-%m') as date,TX1.m3,TX2.m3,TX3.m3
from TX1 AS c1 left join TX2 AS c2 on TX1.date=TX2.date
left join TX3 AS c3 on TX2.date=TX3.date

Which was modified from a previous working script.这是从以前的工作脚本修改而来的。 But the old structure only had 3 tables and now I have seven.但是旧的结构只有 3 张桌子,现在我有 7 张。

UPDATE:Tried the following更新:尝试了以下操作

SELECT TX1.date,TX1.m3,TX2.m3,TX2.m3...TX7.m3
FROM TX1
inner JOIN TX2 ON TX1.date = TX2.date
inner JOIN TX3 ON TX2.date = TX3.date
......
inner JOIN TX7 ON TX6.date = TX7.date

Above code will return an un-grouped matrix.上面的代码将返回一个未分组的矩阵。 Tried to group with 'date' and returned error 1055. Override with试图用“日期”分组并返回错误 1055。覆盖

SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

Now works, but not sure if this is the correct way to do.现在有效,但不确定这是否是正确的方法。 Any ideas?有任何想法吗?

If you want to use the same query structure with addition of newly created tables, you can try using prepared statement.如果您想使用相同的查询结构添加新创建的表,您可以尝试使用准备好的语句。 For example:例如:

Preparing field values:准备字段值:

/*setting variables as NULL*/
SET @sql = NULL;
SET @tbl = NULL;
SET @val1 = NULL;
SET @val2 = NULL;
SET @reftbl = 'TX1'; /*this is your reference (most left) table in the LEFT JOIN*/

/*setting each variables with values*/

SELECT GROUP_CONCAT(CONCAT(table_name,'.',column_name,' AS ',table_name,column_name) SEPARATOR ', ') INTO @val1
FROM information_schema.columns 
WHERE table_name LIKE 'TX%'
#AND table_schema=your_database_name
AND column_name='m3';

SELECT CONCAT(GROUP_CONCAT(CONCAT(table_name,'.',column_name) ORDER BY table_name SEPARATOR '+' ),' as subtotal') INTO @val2
FROM information_schema.columns 
WHERE table_name LIKE 'TX%'
#AND table_schema=your_database_name
AND column_name='m3'

Here we are using information_schema.columns tables to generate field of all the m3 columns coming from all tables that correspond to the condition ( table_name and table_schema ).这里我们使用information_schema.columns表来生成来自与条件( table_nametable_schema )对应的所有表的所有m3列的字段。 This will return you something like:这将返回给你类似的东西:

@val1: TX1.m3 AS TX1m3, TX2.m3 AS TX2m3, TX3.m3 AS TX3m3, TX4.m3 AS TX4m3, TX5.m3 AS TX5m3, TX6.m3 AS TX6m3, TX7.m3 AS TX7m3

@val2:TX1.m3+TX2.m3+TX3.m3+TX4.m3+TX5.m3+TX6.m3+TX7.m3 as subtotal

Next is to prepare the tables required in the query and add LEFT JOIN .接下来是准备查询所需的表并添加LEFT JOIN

SELECT CONCAT(@reftbl, 
          GROUP_CONCAT(
               CASE WHEN tbn IS NOT NULL 
               THEN CONCAT(' LEFT JOIN ', table_name,' ON ',tbn,'.date =',table_name,'.date') 
          ELSE table_name END SEPARATOR ' ')) INTO @tbl
FROM
(SELECT @reftbl tbn,
       table_name 
FROM information_schema.tables 
WHERE table_name LIKE 'TX%'
#AND table_schema=your_database_name
AND table_name <> @reftbl) v;

The operation I'm doing here is to generate the LEFT JOIN parts by using CONCAT and GROUP_CONCAT .我在这里做的操作是使用CONCATGROUP_CONCAT生成LEFT JOIN部分。

Then we set @sql variable with a query generated based on all the variables we previously set;然后我们使用基于我们之前设置的所有变量生成的查询来设置@sql变量; constructed using CONCAT .使用CONCAT构建。

/*constructing query and set into @sql*/
SET @sql = CONCAT('SELECT DATE_FORMAT(TX1.DATE, "%Y-%m") AS DATE,',@val1,',',@val2,'
               FROM ',@tbl,';'); 

This will end up with a query like:这将最终得到如下查询:

SELECT DATE_FORMAT(TX1.DATE, "%Y-%m") AS DATE,TX1.m3 AS TX1m3, TX2.m3 AS TX2m3, 
       TX3.m3 AS TX3m3, TX4.m3 AS TX4m3, TX5.m3 AS TX5m3, TX6.m3 AS TX6m3, TX7.m3 AS TX7m3,
       TX1.m3+TX2.m3+TX3.m3+TX4.m3+TX5.m3+TX6.m3+TX7.m3 as subtotal
FROM TX1 LEFT JOIN TX2 ON TX1.date =TX2.date  
LEFT JOIN TX3 ON TX1.date =TX3.date  
LEFT JOIN TX4 ON TX1.date =TX4.date  
LEFT JOIN TX5 ON TX1.date =TX5.date  
LEFT JOIN TX6 ON TX1.date =TX6.date  
LEFT JOIN TX7 ON TX1.date =TX7.date;

Lastly, prepare, execute then deallocate the @sql statement and you'll get the desired result you're looking for:最后,准备、执行然后释放@sql语句,您将获得所需的结果:

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt; 

This is a way of generating 'dynamic query' which means if/when you add/remove tables, the query will be generated with the additional or without the removed tables.这是一种生成“动态查询”的方法,这意味着如果/当您添加/删除表时,将生成带有附加表或不带已删除表的查询。 For example, if there's a new table TX8 , when you run the queries above, it will include TX8 in the prepared statement as long as it match the condition.例如,如果有一个新表TX8 ,当您运行上面的查询时,只要它与条件匹配,它就会在准备好的语句中包含TX8

Here's a demo fiddle that includes a situation when there's a new table created. 这是一个演示小提琴,其中包括创建新表时的情况。

In another database, this problem would be solved with multiple FULL joins, but since MySql does not support them and simulating them for 7 tables is not an option, I would choose UNION ALL .在另一个数据库中,这个问题可以通过多个FULL连接来解决,但由于 MySql 不支持它们并且不能为 7 个表模拟它们,我会选择UNION ALL

From each table, return 8 columns: 1 for the date, 1 for m3 and 6 null columns.从每个表中,返回 8 列:1 列表示日期,1 列表示m3和 6 个null列。
Use UNION ALL to combine them and finally aggregate:使用UNION ALL组合它们并最终聚合:

SELECT date, 
       MAX(m3_1) m3_1, MAX(m3_2) m3_2, MAX(m3_3) m3_3, MAX(m3_4) m3_4, MAX(m3_5) m3_5, MAX(m3_6) m3_6, MAX(m3_7) m3_7,
       COALECSE(MAX(m3_1), 0) + COALECSE(MAX(m3_2), 0) + COALECSE(MAX(m3_3), 0) + COALECSE(MAX(m3_4), 0) + 
       COALECSE(MAX(m3_5), 0) + COALECSE(MAX(m3_6), 0) + COALECSE(MAX(m3_7), 0) subtotal
FROM (
  SELECT date, m3 m3_1, null m3_2, null m3_3, null m3_4, null m3_5, null m3_6, null m3_7 FROM XT1
  UNION ALL
  SELECT date, null, m3, null, null, null, null, null FROM XT2
  UNION ALL
  SELECT date, null, null, m3, null, null, null, null FROM XT3
  UNION ALL
  ............................................................
  SELECT date, null, null, null, null, null, null, m3 FROM XT7
) t
GROUP BY date

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM