[英]SUM of multiple rows of SUMs in MySQL
I have a query that returns a total
column for every order
: 我有一个查询,返回每个
order
的total
列:
SELECT o.id, o.created, o.status, o.shipping,
SUM(op.price*op.amount*(1+op.tax/100.0))+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0) AS total
FROM orders AS o
LEFT OUTER JOIN order_products as op ON o.id=op.order_id
GROUP BY o.id;
Output of the query 查询的输出
Now I want to calculate the total revenue, so that would be the SUM of these total
columns. 现在,我要计算总收入,因此将是这些
total
列的total
。
I tried using a subquery like this: 我尝试使用像这样的子查询:
SELECT
SUM(total) FROM (
SELECT
SUM(op.price*op.amount*(1+op.tax/100.0))+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0) AS total
FROM orders AS o
LEFT OUTER JOIN order_products as op ON o.id=op.order_id
GROUP BY o.id
) AS foo
;
Output of the query 查询的输出
However: 然而:
SUM(total)
, not foo
SUM(total)
,而不是foo
AS foo
is used for the subquery, not for the top-level SUM()
AS foo
用于子查询,而不是顶级SUM()
AS foo
, it doesn't work AS foo
,它将无法正常工作 How should the query, to SUM multiple rows of SUMs, look? 查询以求和SUM的多行,应该如何看待?
Note:
Those NULL totals
almost certainly won't exist in production, but it'd still be better to use
COALESCE(x, 0)
just to make sure the query executes correctly.
注意:
这些NULL总数
几乎肯定不会在生产中存在,但是最好使用
Seems like this SUM() is fine with NULL values? COALESCE(x, 0)
来确保查询正确执行。
似乎这样的SUM()可以使用NULL值吗?
when you want to alias name to total you have o set it before from not after your select and for checking null you have to set a value for that: 如果您想为名称加上别名,则必须在选择之前而不是之后进行设置,并且要检查是否为null,必须为此设置一个值:
SELECT
SUM(COALESCE(a.total,0)) as foo FROM (
SELECT
SUM(op.price*op.amount*(1+op.tax/100.0))+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0) AS total
FROM orders AS o
LEFT OUTER JOIN order_products as op ON o.id=op.order_id
GROUP BY o.id
) AS a
SELECT
SUM(
COALESCE(op.order_total, 0)
+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)
+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0)
)
AS grand_total
FROM
orders AS o
LEFT OUTER JOIN
(
SELECT
order_id,
SUM(price*amount*(1+tax/100.0)) AS order_total
FROM
order_products
GROUP BY
order_id
)
AS op
ON o.id=op.order_id
EDIT: 编辑:
You've said that : 你说过:
- SUM(x+y+z) / COUNT(op.order_total)
gives 506
SUM(x+y+z) / COUNT(op.order_total)
为506
- AVG(x+y+z)
gives 532
AVG(x+y+z)
得到532
This implies to me that some of the x+y+z
rows are NULL
when x
is NOT NULL
, therefore it appears that y
or z
are NULL
. 在我看来,这意味着当
x
NOT NULL
为NULL
时,某些x+y+z
NOT NULL
,因此看来y
或z
为NULL
。
As y
and z
are COALESCE(?, 0) * (1+o.shipping_tax/100.0)
, it feels like shipping_tax
is sometimes NULL
. 由于
y
和z
为COALESCE(?, 0) * (1+o.shipping_tax/100.0)
,因此感觉 shipping_tax
有时为NULL
。
Try this query... 试试这个查询...
SELECT
SUM(
COALESCE(op.order_total, 0)
+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)
+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0)
)
AS grand_total,
AVG(
COALESCE(op.order_total, 0)
+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)
+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0)
)
AS grand_average,
COUNT(
COALESCE(op.order_total, 0)
+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)
+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0)
)
AS grand_row_count,
COUNT(
*
)
AS set_row_count,
COUNT(
o.shipping_tax
)
AS shipping_tax_row_count,
AVG(
COALESCE(op.order_total, 0)
+(COALESCE(o.shipping, 0)+COALESCE(o.payment_fee, 0))
*COALESCE(1+o.shipping_tax/100.0, 1)
)
AS revised_grand_average
FROM
orders AS o
LEFT OUTER JOIN
(
SELECT
order_id,
SUM(price*amount*(1+tax/100.0)) AS order_total
FROM
order_products
GROUP BY
order_id
)
AS op
ON o.id=op.order_id
I expect that... 我希望 ...
- grand_average == grand_total / grand_row_count
grand_average == grand_total / grand_row_count
- set_row_count > grand_row_count
set_row_count > grand_row_count
- grand_row_count == shipping_tax_row_count
grand_row_count == shipping_tax_row_count
If so, then the revised_grand_average
should be useful to you. 如果是这样,那么
revised_grand_average
应该对您有用。
If not, then hopefully this gives you a place to start investigating. 如果不是,那么希望这给您一个开始调查的地方。
You don't need a subquery. 您不需要子查询。 Just remove the
GROUP BY
from the original query: 只需从原始查询中删除
GROUP BY
:
SELECT SUM(op.price*op.amount*(1+op.tax/100.0))+COALESCE(o.shipping, 0)*(1+o.shipping_tax/100.0)+COALESCE(o.payment_fee, 0)*(1+o.shipping_tax/100.0) AS total
FROM orders o LEFT OUTER JOIN
order_products op
ON o.id = op.order_id;
This will do the calculation over all the rows. 这将对所有行进行计算。 It should be faster than two levels of aggregation.
它应该快于两个级别的聚合。
The result will be in a column called total
. 结果将在称为
total
的列中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.