在MySQL
中,我尝试根据字段对表进行分组,但在每个组中输出某些字段的总和和最后一个值。对于每个问题,我都有解决方案,但两者都没有。
通过一个例子来解释会更容易。假设这是我们拥有的数据:
CREATE TABLE IF NOT EXISTS `trades` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trader` int(11) NOT NULL,
`volume` int(11) NOT NULL,
`cash` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `trades` (`id`, `trader`, `volume`, `cash`) VALUES
(1, 1, 5, 0),
(2, 1, 7, 5),
(3, 1, 4, 2),
(4, 2, 10, 10);
所以我们的表格如下:
+----+--------+--------+------+
| id | trader | volume | cash |
+----+--------+--------+------+
| 1 | 1 | 5 | 0 |
| 2 | 1 | 7 | 5 |
| 3 | 1 | 4 | 2 |
| 4 | 2 | 10 | 10 |
+----+--------+--------+------+
现在,为了按trader
分组并获得卷的总和,我们执行:
mysql> select trader, sum(volume) from trades group by trader;
+--------+-------------+
| trader | sum(volume) |
+--------+-------------+
| 1 | 16 |
| 2 | 10 |
+--------+-------------+
这很容易。现在,为了获得每个组中的“最后”现金值,其中“最后”在这里我的意思是“最大的id
”(但一般来说,这可以使用任何其他字段进行排序),I可以使用following clever idea(另请参阅here):
mysql> select t1.trader, t1.cash
-> from trades t1 left join trades t2
-> on t1.trader = t2.trader and t1.id < t2.id
-> where t2.id is null;
+--------+------+
| trader | cash |
+--------+------+
| 1 | 2 |
| 2 | 10 |
+--------+------+
但是我如何结合这些解决方案,或者找到不同的解决方案,以获得看起来或多或少的结果如下:
+--------+--------+------+
| trader | volume | cash |
+--------+--------+------+
| 1 | 16 | 2 |
| 2 | 10 | 10 |
+--------+--------+------+
重要说明:我不想使用非健壮的解决方案,但在ONLY_FULL_GROUP_BY
is enabled时失败。
另一个注意事项:我希望能够获得多个字段的“最后”值,但是对于单个排序这样做应该没问题。
答案 0 :(得分:1)
在MySQL中基本上有三种方法:
substring_index()
/ group_concat()
技巧。其中最后一项有一定的局限性。它将所有值转换为字符串。并且作为字符串的中间值的数量受参数group_concat_maxlen
(可以更改)的限制。但是,当您已经进行聚合时,它是最简单的:
select trader, sum(volume),
substring_index(group_concat(cash order by id desc), ',', 1) as last_cash
from trades
group by trader;
使用join
的方法如下:
select t.trader, sum(t.volume),
max(case when t.id = tt.maxid then cash end) as last_cash
from trades t left join
(select trader, max(id) as maxid
from trades t
group by trader
) tt
on t.trader = tt.trader
group by t.trader;
答案 1 :(得分:1)
您可以使用子查询查找每个交易者的总和和最大ID,然后加入表本身以获得现金值;
SELECT t1.trader, t2.volume, t1.cash
FROM trades t1
JOIN (
SELECT trader, MAX(id) maxid, SUM(volume) volume FROM trades GROUP BY trader) t2
ON t1.id = t2.maxid