Mysql子select with SUM() and group by

时间:2021-08-18 01:32:21

I am trying to create a query that does a calculation in a subquery that requires the SUM function and a group by. My query returns the error "Subquery returns more than 1 row". Essentially I am trying to return the amount "Due" for each order. If the order total is greater than the sum of total_collected (for that order_id) from the payments table there will be amount due. Here is the query:

我正在尝试创建一个查询,该查询在需要SUM函数和group by的子查询中执行计算。我的查询返回错误“子查询返回多于一行”。本质上,我试图返回每个订单的“到期金额”。如果订单总数大于从付款表中收集的total_collected(对于该order_id)的总和,那么将会有相应的金额。在这里查询:

SELECT o.order_id
     , o.server
     , o.subtotal
     , o.discount
     , o.tax, o.total
     , (SELECT (o.total - SUM(p.total_collected)) 
            from orders o 
            join payments p 
              on o.order_id = p.order_id 
        group by p.order_id) as 'Due'
  FROM orders o 
  join payments p 
    on o.order_id = p.order_id
WHERE...;

I cannot include 'p.order_id' in the sub select because it should only contain one column. I understand why I am getting the error, I just don't know how to get the sub select to only perform the SUM on a per order_id basis.

我不能包括“p。在子选择中order_id,因为它只包含一个列。我理解为什么会出现错误,我只是不知道如何让subselect只在order_id的基础上执行和。

2 个解决方案

#1


2  

Without changing the structure much, I think the subquery is looking at all of the data in the orders/payments tables. I think you need to filter it down to look only at the relevant order_id like so.

在不改变结构的情况下,我认为子查询将查看订单/付款表中的所有数据。我认为您需要将其过滤,以便只查看相关的order_id。

(I also added a SUM around the order total because I am pretty sure that would give a different error without it.)

(我还在订单总数上加了一个和,因为我很确定没有它会产生不同的错误。)

SELECT o.order_id
     , o.server
     , o.subtotal
     , o.discount
     , o.tax
     , o.total
     , (SELECT (SUM(o2.total) - SUM(p.total_collected))
            from orders o2 
            JOIN payments p 
              ON o2.order_id = p.order_id
            WHERE o2.order_id = o.order_id) as 'Due'
    FROM orders o
WHERE...;

Although, if you adjust this so that it uses a join instead of a subquery, I think you will get better performance. Something like this:

虽然,如果您调整它,使它使用连接而不是子查询,我认为您将获得更好的性能。是这样的:

SELECT o.order_id
     , o.server
     , o.subtotal
     , o.discount
     , o.tax
     , o.total
     , o.total - c.Collected AS 'Due'
    FROM orders o
    JOIN (
        SELECT p2.order_id, SUM(p2.total_collected) AS 'Collected'
          FROM payments p2
        GROUP BY p2.order_id) AS c
      ON o.order_id = c.order_id
WHERE...;

#2


1  

You do not need sub-query:

不需要子查询:

SELECT
  o.order_id,
  o.server,
  o.subtotal,
  o.discount,
  o.tax,
  o.total,
  o.total - ifnull(sum(p.total_collected),0) As Due
FROM orders AS o 
LEFT JOIN payments AS p ON o.order_id = p.order_id
WHERE ...
GROUP BY o.order_id

#1


2  

Without changing the structure much, I think the subquery is looking at all of the data in the orders/payments tables. I think you need to filter it down to look only at the relevant order_id like so.

在不改变结构的情况下,我认为子查询将查看订单/付款表中的所有数据。我认为您需要将其过滤,以便只查看相关的order_id。

(I also added a SUM around the order total because I am pretty sure that would give a different error without it.)

(我还在订单总数上加了一个和,因为我很确定没有它会产生不同的错误。)

SELECT o.order_id
     , o.server
     , o.subtotal
     , o.discount
     , o.tax
     , o.total
     , (SELECT (SUM(o2.total) - SUM(p.total_collected))
            from orders o2 
            JOIN payments p 
              ON o2.order_id = p.order_id
            WHERE o2.order_id = o.order_id) as 'Due'
    FROM orders o
WHERE...;

Although, if you adjust this so that it uses a join instead of a subquery, I think you will get better performance. Something like this:

虽然,如果您调整它,使它使用连接而不是子查询,我认为您将获得更好的性能。是这样的:

SELECT o.order_id
     , o.server
     , o.subtotal
     , o.discount
     , o.tax
     , o.total
     , o.total - c.Collected AS 'Due'
    FROM orders o
    JOIN (
        SELECT p2.order_id, SUM(p2.total_collected) AS 'Collected'
          FROM payments p2
        GROUP BY p2.order_id) AS c
      ON o.order_id = c.order_id
WHERE...;

#2


1  

You do not need sub-query:

不需要子查询:

SELECT
  o.order_id,
  o.server,
  o.subtotal,
  o.discount,
  o.tax,
  o.total,
  o.total - ifnull(sum(p.total_collected),0) As Due
FROM orders AS o 
LEFT JOIN payments AS p ON o.order_id = p.order_id
WHERE ...
GROUP BY o.order_id