如何合并查询并计算datas与abc_datas表的指定字段总和?
合并两个数据表数值总和的优化方案
看来你已经通过子查询实现了需求,但我可以帮你梳理下之前UNION ALL写法的问题,再给几个更高效的备选方案:
为啥你之前的UNION ALL没得到预期结果?
你原来的SQL写法:
SELECT *, SUM(amount) AS total_sum1 FROM datas WHERE user_id = $user_id UNION ALL SELECT *, SUM(amount) AS total_sum2 FROM abc_datas WHERE user_id = $user_id;
问题出在这几点:
- 每个子查询里的
SELECT *加上SUM(amount),在没有GROUP BY的情况下,会返回单条记录(表中第一条数据的所有字段 + 该表的amount总和) UNION ALL把这两个单条结果合并成了一个包含两条记录的结果集,但你用->row()只取了第一条,自然看不到第二个表的总和
如果非要用UNION ALL实现单字段总和,得在外层再套一层聚合:
SELECT SUM(total_sum) AS total_sum FROM ( SELECT SUM(amount) AS total_sum FROM datas WHERE user_id = $user_id UNION ALL SELECT SUM(amount) AS total_sum FROM abc_datas WHERE user_id = $user_id ) AS sums
不过这只能算单个字段,要同时算amount、agent_amount、profit三个字段的总和,下面的方案更合适。
方案1:先合并数据集再聚合(性能最优)
这种方式只需要对每个表做一次筛选查询,然后在合并后的结果上一次性计算所有总和,避免重复扫描表:
$query = $this->db->query(" SELECT SUM(amount) AS total_sum, SUM(agent_amount) AS total_agent_amount, SUM(profit) AS total_profit FROM ( -- 先把两个表中符合条件的字段合并 SELECT amount, agent_amount, profit FROM datas WHERE user_id = $user_id UNION ALL SELECT amount, agent_amount, profit FROM abc_datas WHERE user_id = $user_id ) AS combined_data "); return $query->row();
数据量大的时候,这个方法比你原来的子查询写法高效很多——原来的写法每个字段都单独查了两次表,总共6次表查询,而这个写法只需要2次。
方案2:简化版子查询(兼顾可读性与性能)
如果你更习惯子查询的写法,可以优化成每个表只查一次,把所有需要的聚合值都算出来再相加:
$query = $this->db->query(" SELECT (d.total_amount + ad.total_amount) AS total_sum, (d.total_agent + ad.total_agent) AS total_agent_amount, (d.total_profit + ad.total_profit) AS total_profit FROM ( -- 一次性查出datas表的三个聚合值 SELECT SUM(amount) AS total_amount, SUM(agent_amount) AS total_agent, SUM(profit) AS total_profit FROM datas WHERE user_id = $user_id ) AS d, ( -- 一次性查出abc_datas表的三个聚合值 SELECT SUM(amount) AS total_amount, SUM(agent_amount) AS total_agent, SUM(profit) AS total_profit FROM abc_datas WHERE user_id = $user_id ) AS ad "); return $query->row();
这个写法只需要查询两次表,比你原来的子查询减少了4次重复查询,性能更好,可读性也更强。
内容的提问来源于stack exchange,提问作者user_777
相关产品推荐
相关产品推荐

