更好的SQL在多个表中对相同的列进行求和?

时间:2014-02-15 04:39:00

标签: mysql sql sum

我正在尝试使用python / sqlalchemy从多个mysql表中获取一些列的总和。表的数量是动态的,每个表都有相同的架构。

Table_1
| col1 | col2| ... |

Table_2
| col1 | col2| ... |

Table_...
| col1 | col2| ... |

我研究了sqlachemy,并意识到更好的想法可能是生成SQL文本并执行它,创建模型可能不是一个好的解决方案,我觉得可能会在性能上引入额外的成本,我更喜欢单个SQL语句。

select (t1.col1 + t2.col1 + t3.col1 + t?.col1 ...) as col1, (t1.col2 + t2.col2 + ...) as col2,
 ... from
(select sum(col1), sum(col2), sum(col3) ... from Table_1 as t1,
 select sum(col1), sum(col2), sum(col3) ... from Table_2 as t2,
 ...
)

以上是我打算使用python创建的SQL。我不是SQL专业人士,所以我不确定这是否是一个好的陈述,我想知道是否有更好的解决方案,更简单和有效,除此之外?

3 个答案:

答案 0 :(得分:1)

您的一般方法看起来很合理。将各个表中的SUM作为单行获取,并将它们组合在一起,是最有效的方法。只有几个小修复。

看起来您需要为返回的每个SUM()表达式提供别名。

并且你需要将每个表中的SELECT包装在一组parens中,并为每个内联视图赋予别名。

此外,内部SUM()表达式之一可能会返回NULL,因此在外部查询中执行的添加可能会返回NULL。一个修复方法是将内部SUM表达式包装在IFNULL或COALESCE中,用零替换NULL,但这可能会引入一个零,其中外部SUM实际上是NULL。

就个人而言,我会避免在JOIN操作中使用逗号表示法。逗号有效,但我会使用CROSS JOIN关键字将其写出来,以使其更具可读性。

但我的偏好是避免外部查询中的JOIN和添加操作。我在外部查询中使用SUM聚合,如下所示:

SELECT SUM(t.col1_tot) AS col1_tot
     , SUM(t.col2_tot) AS col2_tot
     , SUM(t.col3_tot) AS col3_tot
  FROM ( SELECT SUM(col1) AS col1_tot
              , SUM(col2) AS col2_tot 
              , SUM(col3) AS col3_tot 
           FROM table1
          UNION ALL
         SELECT SUM(col1) AS col1_tot
              , SUM(col2) AS col2_tot 
              , SUM(col3) AS col3_tot 
           FROM table2
          UNION ALL
         SELECT SUM(col1) AS col1_tot
              , SUM(col2) AS col2_tot
              , SUM(col3) AS col3_tot 
           FROM table3
       ) t

这可以避免使用NULL值出现异常,并使其返回的值与将各个表连接在一起时返回的值相同。但这并不比你拥有的更有效率。


要使用JOIN方法,就像在查询中一样(如果我不介意在上面的查询中返回一个返回NULL的地方,那么该方法可以工作:

SELECT t1.col1_tot + t2.col1_tot + t3.col1_tot  AS col1_tot
     , t1.col2_tot + t2.col2_tot + t3.col2_tot  AS col2_tot
     , t1.col3_tot + t2.col3_tot + t3.col3_tot  AS col3_tot
  FROM ( SELECT IFNULL(SUM(col1),0) AS col1_tot
              , IFNULL(SUM(col2),0) AS col2_tot 
              , IFNULL(SUM(col3),0) AS col3_tot 
           FROM table1
       ) t1
 CROSS  
  JOIN ( SELECT IFNULL(SUM(col1),0) AS col1_tot
              , IFNULL(SUM(col2),0) AS col2_tot 
              , IFNULL(SUM(col3),0) AS col3_tot 
           FROM table2
       ) t2
 CROSS  
  JOIN ( SELECT IFNULL(SUM(col1),0) AS col1_tot
              , IFNULL(SUM(col2),0) AS col2_tot 
              , IFNULL(SUM(col3),0) AS col3_tot
       ) t3

但是,我个人的偏好是避免在外部查询中执行这些添加操作。我使用SUM聚合,UNION来自各个表的结果,而不是进行连接。

答案 1 :(得分:0)

除非你有一些where子句将这些表连接在一起,否则你将最终得到一个笛卡尔连接,其中查询中每个表的每个记录都与其他表中的所有其他记录组合相连。因此,如果每个表都有(比方说)1000条记录,并且查询中有5个表,那么结果集中最终会得到1000 ^ 5 = 1,000,000,000,000,000条记录。

你想要的可能更像是这样:

SELECT sum(col1) AS sum1, sum(col2) AS sum2, ....
FROM (
   SELECT col1, col2, col3, ... FROM table1
   UNION ALL
   SELECT col1, col2, col3, ... FROM table2
   UNION ALL
   ...
) a

内部UNION连接将获取每个表中的所有列,并将它们转换为单个连续的结果集。然后,外部查询将获取每个列并总结值。

答案 2 :(得分:0)

这可能有助于你,

select SUM(col1),SUM(col2) from
(
select col1,col2 from Table1 
union all
select col1,col2 from Table2
union all
select col1,col2 from Table3 
)t