鉴于此样本数据:
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个查询中进行此操作,是否可能?
问题是:根据我的表格,计算所有付款后的用户余额。
这就是我现在正在做的事情:将每个用户的所有付款分组并汇总,并用 - 符号标记结果。并将所有付款分组并汇总给每个用户,并用+号标记。联合这个结果,然后又在那个总和和组之后。
有更好的方法吗?
答案 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
列,其值为from
或to
。这样选择将如下所示:
SELECT `userid` , SUM(IF(`payment_type` = `from`,`amount`, -`amount`)) AS `balance`
FROM `payments`
GROUP BY `userid`;