In MySQL
, I am trying to group a table according to a field, but in each of these groups output both the sum and the last value of some fields. For each of the problems I have a solution, but not for both.
It would be easier to explain by an example. Suppose this is the data we have:
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);
So our table looks as follows:
+----+--------+--------+------+
| id | trader | volume | cash |
+----+--------+--------+------+
| 1 | 1 | 5 | 0 |
| 2 | 1 | 7 | 5 |
| 3 | 1 | 4 | 2 |
| 4 | 2 | 10 | 10 |
+----+--------+--------+------+
Now, in order to group by trader
and get the sum of the volumes, we perform:
mysql> select trader, sum(volume) from trades group by trader;
+--------+-------------+
| trader | sum(volume) |
+--------+-------------+
| 1 | 16 |
| 2 | 10 |
+--------+-------------+
which is easy. Now, in order to get the "last" cash value in each group, where by "last" here I mean "of the largest id
" (but in general, this could use any other field for ordering), I can use the following clever idea (see also 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 |
+--------+------+
But how can I combine these solutions, or perhaps find a different solution, in order to get a result which looks more or less as follows:
+--------+--------+------+
| trader | volume | cash |
+--------+--------+------+
| 1 | 16 | 2 |
| 2 | 10 | 10 |
+--------+--------+------+
Important note: I don't want to use non robust solutions, that fail when ONLY_FULL_GROUP_BY
is enabled.
Another note: I wish to be able to get the "last" value of more than one field, but doing it with respect to a single ordering should be fine.