mysql多个记录集来自group by

时间:2014-11-06 22:19:57

标签: mysql sql sql-optimization

鉴于此样本数据:

CREATE TABLE payments(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  fromid INT UNSIGNED NOT NULL DEFAULT 0,
  toid INT UNSIGNED NOT NULL DEFAULT 0,
  amount INT UNSIGNED NOT NULL DEFAULT 0,
  PRIMARY KEY (id)
);
INSERT INTO payments
(fromid, toid, amount)
VALUES
(1, 2, 10),
(1, 3, 20),
(1, 4, 30),
(2, 4, 10),
(4, 3, 20);

和这个查询:

SELECT `toid` AS `userid`, 
SUM(`grouped_amount`) AS `balance` 
FROM (
   SELECT `t2`.`toid`, SUM(`t2`.`amount`) AS `grouped_amount`
   FROM (
       SELECT * FROM `payments`
   ) AS `t2` GROUP BY `toid` UNION 
   SELECT `t1`.`fromid`, -SUM(`t1`.`amount`)
   FROM (
       SELECT * FROM `payments`
   )AS `t1` GROUP BY `fromid`)
AS `t` GROUP BY `toid`;

Here是我的桌子和工作结果的平方米,但我担心表现。有2个完全相同的子查询。我想在1个查询中进行此操作,是否可能?

问题是:根据我的表格,计算所有付款后的用户余额。

这就是我现在正在做的事情:将每个用户的所有付款分组并汇总,并用 - 符号标记结果。并将所有付款分组并汇总给每个用户,并用+号标记。联合这个结果,然后又在那个总和和组之后。

有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您的查询几乎没问题,您只是嵌套超过必要的。写得像这样:

SELECT userid, SUM(mysum) AS Balance
FROM (

    SELECT
    toid as userid, SUM(amount) as mysum
    FROM payments
    GROUP BY toid

UNION ALL

    SELECT
    fromid, SUM(amount) * -1
    FROM payments
    GROUP BY fromid

) sq
GROUP BY userid;

没有什么改进空间,为了满足您的要求,您很难以另一种方式写出来。我做了UNION ALL而不是UNION。区别在于,UNION没有ALL意味着您不需要/想要的DISTINCT

答案 1 :(得分:0)

我认为你可以减少开销:

SELECT `userid` , SUM(`amount`) AS `balance` 
FROM (
   SELECT `toid` AS `userid`, `amount`
   FROM `payments`
   UNION ALL
   SELECT `fromid` AS `userid`, -1*`amount` AS `amount`
   FROM `payments`
) AS `t` 
GROUP BY `userid`;

删除UNION操作的解决方案是改变一点'你的模特。您只需拥有一个userid字段,以及另一个payment_type列,其值为fromto。这样选择将如下所示:

SELECT `userid` , SUM(IF(`payment_type` = `from`,`amount`, -`amount`)) AS `balance` 
FROM `payments`
GROUP BY `userid`;