繁体   English   中英

MySQL中SUM的多行总和

[英]SUM of multiple rows of SUMs in MySQL

我有一个查询,返回每个ordertotal列:

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;

第一个查询的输出

查询的输出

现在,我要计算总收入,因此将是这些total列的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
;

第二个查询的输出

查询的输出

然而:

  • 结果列名为SUM(total) ,而不是foo
    • 似乎AS foo用于子查询,而不是顶级SUM()
  • 没有AS foo ,它将无法正常工作
  • 该查询返回的结果可能不正确, 但这可能是由于rounding引起的

查询以求和SUM的多行,应该如何看待?

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

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

编辑:

你说过:
SUM(x+y+z) / COUNT(op.order_total)506
AVG(x+y+z)得到532

在我看来,这意味着当x NOT NULLNULL时,某些x+y+z NOT NULL ,因此看来yzNULL

由于yzCOALESCE(?, 0) * (1+o.shipping_tax/100.0) ,因此感觉 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
grand_row_count == shipping_tax_row_count

如果是这样,那么revised_grand_average应该对您有用。

如果不是,那么希望这给您一个开始调查的地方。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM