Mysql查询 - 操作数应包含1列

时间:2016-06-04 07:24:24

标签: mysql sql subquery left-join

我在这里讨论了几个主题,但是我无法让它发挥作用。对于每个"锅"我想获得与此底池相关的付款数量以及全额佣金(所有付款佣金的总和)。

SELECT id, id_user,
       ( SELECT IFNULL( SUM(amount), 0 ) AS collectedA, 
                IFNULL( SUM(commission), 0 ) AS commission 
                FROM payment AS pay WHERE pay.id_pot = pot.id AND pay.stat = 1 ) FROM pot

上面给出了标题中提到的错误。我知道我们不能用这种子查询选择两列。 我试图通过LEFT OUTER JOIN但无法让它工作。

SELECT id, id_user, 
       IFNULL( SUM(payment.amount), 0 ) AS collectedA, 
       IFNULL( SUM(payment.commission), 0 ) AS commission
FROM pot LEFT OUTER JOIN payment ON payment.id_pot = pot.id AND payment.stat = 1

但这给了我奇怪的结果......

3 个答案:

答案 0 :(得分:2)

您必须LEFT JOIN已聚合的派生表,如下所示:

SELECT id, id_user, collectedA, commission 
FROM pot 
LEFT JOIN (
   SELECT id_pot,
          IFNULL( SUM(amount), 0 ) AS collectedA, 
          IFNULL( SUM(commission), 0 ) AS commission 
   FROM payment  
   WHERE stat = 1 
   GROUP BY id_pot
) AS pay pay.id_pot = pot.id

子查询中执行的GROUP BY可确保您每pot.id只能获得一条记录

答案 1 :(得分:1)

您的LEFT JOIN是正确的,但您忘记使用GROUP BY

SELECT pot.id, id_user, 
       IFNULL( SUM(payment.amount), 0 ) AS collectedA, 
       IFNULL( SUM(payment.commission), 0 ) AS commission
FROM pot 
LEFT OUTER JOIN payment ON payment.id_pot = pot.id AND payment.stat = 1
GROUP BY pot.id

如果您需要WHERE子句来仅选择部分花盆,请将其放在LEFT OUTER JOIN之后。

SELECT pot.id, id_user, 
       IFNULL( SUM(payment.amount), 0 ) AS collectedA, 
       IFNULL( SUM(payment.commission), 0 ) AS commission
FROM pot 
LEFT OUTER JOIN payment ON payment.id_pot = pot.id AND payment.stat = 1
WHERE ...
GROUP BY pot.id

答案 2 :(得分:1)

最有效的方法可能是两个子查询,特别是如果你想在pot表上有过滤器:

select pot.id, pot.id_user,
       (select sum(pay.amount)
        from payment pay
        where pay.id_pot = pot.id and pay.stat = 1
       ) as amount,
       (select sum(pay.commission)
        from payment pay
        where pay.id_pot = pot.id and pay.stat = 1
       ) as commission
from pot;

为了有效地工作,您需要payment(id_pot, stat, amount, commission)上的索引。这是两个查询的覆盖索引(意味着所有列都在索引中。

这似乎违反直觉,这更快,但它不需要全局聚合 - 所有聚合都可以使用索引扫描来处理。这通常更快。此外,pot上的任何其他过滤器都会减少payment表的工作量。