MySQL中SUM的多行总和

时间:2018-09-24 17:52:11

标签: mysql sql

我有一个查询,它为每个total返回一个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 first query

查询输出

现在,我要计算总收入,因此将是这些total列的总和。

我尝试使用这样的子查询:

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 second query

查询输出

但是:

  • 结果列名为SUM(total),而不是foo
    • 好像AS foo用于子查询,而不是顶层SUM()
  • 如果没有AS foo,它将无法正常工作
  • 此查询返回的结果可能不正确,但可能是由于四舍五入

查询如何汇总SUM的多行?

注意:这些NULL总计几乎当然不会在生产中存在,但最好使用COALESCE(x, 0)来确保查询正确执行。似乎这样的SUM()可以使用NULL值吗?

3 个答案:

答案 0 :(得分:1)

当您想为总名称加上别名时,请在选择之前而不是之后进行设置,并且要检查是否为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

答案 1 :(得分:1)

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

编辑:

您已经说过:
 -SUM(x+y+z) / COUNT(op.order_total)给出506
 -AVG(x+y+z)给出532

这对我来说意味着x+y+zNULL时,某些x行是NOT NULL,因此看来y或{{1} }是z

由于NULLyz,所以 感觉 COALESCE(?, 0) * (1+o.shipping_tax/100.0)有时为{{1} }。

尝试此查询...

shipping_tax

期望 ......
 -NULL
 -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
 -grand_average == grand_total / grand_row_count

如果是这样,那么set_row_count > grand_row_count应该对您有用。

如果没有,那么希望这可以为您提供一个开始调查的地方。

答案 2 :(得分:0)

您不需要子查询。只需从原始查询中删除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;

这将对所有行进行计算。它应该快于两个级别的聚合。

结果将在名为total的列中。