[英]SUM of a quantity column when using INNER JOIN and distinct/group by
[英]Getting wrong sum when using group by with inner join
参考这个问题( How to get the sum in a join table when using group by-get wrong results )我有两个表orders
和order_items
。 我需要按天对结果进行分组。 但我还需要从另一个表中获取每天的energy_used
总和。 当我尝试使用连接时,我每天都会得到错误的order_sum
(它们没有被总结)。 不知道我做错了什么。
我想得到每一天
order_items.energy_used
总和orders.order_sum
总和order
对应的created_at
和order_sum
这是我的orders
表
+----+-----------+---------+---------------------+
| id | order_sum | user_id | created_at |
+----+-----------+---------+---------------------+
| 1 | 25.13 | 7 | 2020-01-25 09:13:00 |
| 2 | 10.00 | 7 | 2020-01-25 15:23:00 |
| 3 | 14.00 | 5 | 2020-01-26 10:14:00 |
| 4 | 35.00 | 1 | 2020-01-27 11:13:00 |
+----+-----------+---------+---------------------+
这是我的order_items
表
+----+----------+-------------+---------------------+
| id | order_id | energy_used | created_at |
+----+----------+-------------+---------------------+
| 1 | 1 | 65 | 2020-01-25 09:13:00 |
| 2 | 1 | 12 | 2020-01-25 09:13:00 |
| 3 | 2 | 70 | 2020-01-26 10:14:00 |
| 4 | 2 | 5 | 2020-01-26 10:14:00 |
| 5 | 3 | 0 | 2020-01-27 11:13:00 |
+----+----------+-------------+---------------------+
这是我想要达到的预期结果
+---------------+-----------------+-------------------+---------------------+----------------+
| date_of_month | total_order_sum | total_energy_used | last_order_date | last_order_sum |
+---------------+-----------------+-------------------+---------------------+----------------+
| 2020-01-25 | 35.13 | 77 | 2020-01-25 09:13:00 | 25.13 |
| 2020-01-26 | 14.00 | 75 | 2020-01-26 10:14:00 | 14.00 |
| 2020-01-27 | 35.00 | 0 | 2020-01-27 11:13:00 | 35.00 |
+---------------+-----------------+-------------------+---------------------+----------------+
这是我尝试过的查询,但我得到了错误的结果,order_sum 没有正确计算。 它显示与last_order_sum
相同
select
date(o.created_at) date_of_month,
i.total_energy_used,
o.created_at last_order_date,
o.order_sum last_order_sum,
sum(order_sum) as total_order_sum
from orders o
inner join (
select date(o1.created_at) date_of_month, sum(i1.energy_used) total_energy_used
from orders o1
inner join order_items i1 on o1.id = i1.order_id
group by date(o1.created_at)
) i on i.date_of_month = date(o.created_at)
where o.created_at = (
select max(o1.created_at)
from orders o1
where date(o1.created_at) = date(o.created_at)
)
这是一个小提琴: https ://dbfiddle.uk/ ? rdbms = mysql_5.6 & fiddle =92b8cc2920ad9f7a7cdd56bded5a3bf2
始终根据它们的关系将表连接在一起(在这种情况下,orders.id 和 order_items.order_id)然后分组。 为了避免在加入时为多个 order_items 复制 order_sums,首先按 order_id 对 order_items 进行分组。
select
date(o.created_at) date_of_month,
sum(i.total_energy_used),
max(o.created_at),
sum(order_sum) as total_order_sum
from orders o
inner join (
select order_id, sum(total_energy_used) total_energy_used
from order_items i
group by order_id
) i on o.id = i.order_id
group by date(o.created_at)
从这一点开始,您可以使用 max(o.created_at) 再次对订单进行连接,以获取最后一个订单的 order_sum。 故事的寓意:注意你的粒度。
您的问题是您正在从orders
进行选择,而您实际上想要按日期汇总orders
。 因此,请从您加入的两个聚合子查询中进行选择。 唯一的问题是last_order_sum
,一旦我们知道最后的订单日期,我们就可以在进一步的子查询中选择它。
select
order_date,
o.total_order_sum,
oi.total_energy_used,
o.last_order_date,
(
select order_sum
from orders last_order
where lastorder.created_at = o.last_order_date
) as last_order_sum
from
(
select
date(created_at) as order_date,
sum(order_sum) as total_order_sum,
max(created_date) as last_order_date
from orders
group by date(created_at)
) o
inner join
(
select
date(created_at) as order_date,
sum(energy_used) as total_energy_used
from order_items
group by date(created_at)
) oi using(order_date)
order by order_date;
您要问的内容与您在输出中向我们展示的内容无关。 假设这是一个错字:
select so.dtDay as date_of_month, so.order_sum as total_order_sum,
eu.energy_used as total_energy_used,
o.created_at as last_order_date,
o.order_sum as last_order_sum
from (
select left(created_at,10) as dtDay, sum(order_sum) as order_sum, max(id) as last_insert_id
from orders
group by left(created_at,10)
order by created_at
) so
inner join orders o on o.id = so.last_insert_id
left join (select left(created_at,10) as dtDay, sum(energy_used) as energy_used
from order_items
group by left(created_at,10)) eu on so.dtDay = eu.dtDay;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.