I have a query that returns a total
column for every order
:
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.
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
AS foo
is used for the subquery, not for the top-level SUM()
AS foo
, it doesn't work How should the query, to SUM multiple rows of SUMs, look?
Note:
Those NULL totals
almost certainly won't exist in production, but it'd still be better to use
Seems like this SUM() is fine with NULL values? COALESCE(x, 0)
just to make sure the query executes correctly.
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:
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
- AVG(x+y+z)
gives 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
.
As y
and z
are COALESCE(?, 0) * (1+o.shipping_tax/100.0)
, it feels like shipping_tax
is sometimes 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
- set_row_count > grand_row_count
- grand_row_count == shipping_tax_row_count
If so, then the revised_grand_average
should be useful to you.
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:
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
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.