鉴于此示例数据:
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是我的表和工作结果的 sqlfiddle,但我担心性能。有 2 个完全相同的子查询。我想在 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
。不同之处在于,不带 ALL
的 UNION
表示您不需要/不想要的 DISTINCT
。
关于mysql从group by设置多条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26790483/