I'm doing some coronavirus statistics. Would you help me with a query, please. I'd like to get the LAST infected ('confirmed' field) growth for each country. Some countries doesn't update every day, so it needs to be a difference between second last meassure and the last one for each country.
In short - how to find last value increase in a groupped table?
The table looks like this:
CREATE TABLE coronavirus (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
place VARCHAR(30),
province VARCHAR(30),
country VARCHAR(40),
updated TIMESTAMP,
confirmed INTEGER,
deaths INTEGER,
recovered INTEGER,
latitude FLOAT,
longitude FLOAT);
Thanks!
PS. The table contents looks like this:
mysql> select * from coronavirus where id>8000 order by id limit 10;
+------+-------+-----------------+-------------+---------------------+-----------+--------+-----------+----------+-----------+
| id | place | province | country | updated | confirmed | deaths | recovered | latitude | longitude |
+------+-------+-----------------+-------------+---------------------+-----------+--------+-----------+----------+-----------+
| 8001 | NULL | Shanghai | China | 2020-03-23 14:18:01 | 404 | 4 | 329 | 31.202 | 121.449 |
| 8002 | NULL | Shanxi | China | 2020-03-13 08:56:40 | 133 | 0 | 133 | 37.5777 | 112.292 |
| 8003 | NULL | Sichuan | China | 2020-03-22 07:20:38 | 543 | 3 | 536 | 30.6171 | 102.71 |
| 8004 | NULL | Sint Maarten | Netherlands | 2020-03-23 23:19:21 | 2 | 0 | 0 | 18.0425 | -63.0548 |
| 8005 | NULL | South Australia | Australia | 2020-03-23 23:23:20 | 134 | 0 | 6 | -34.9285 | 138.601 |
| 8006 | NULL | St Martin | France | 2020-03-23 23:19:21 | 8 | 0 | 0 | 18.0708 | -63.0501 |
| 8007 | NULL | Tasmania | Australia | 2020-03-23 23:23:20 | 28 | 0 | 3 | -42.8821 | 147.327 |
| 8008 | NULL | Tianjin | China | 2020-03-23 03:57:57 | 141 | 3 | 133 | 39.3054 | 117.323 |
| 8009 | NULL | Tibet | China | 2020-02-23 11:19:02 | 1 | 0 | 1 | 31.6927 | 88.0924 |
| 8010 | NULL | Victoria | Australia | 2020-03-23 23:23:20 | 355 | 0 | 97 | -37.8136 | 144.963 |
+------+-------+-----------------+-------------+---------------------+-----------+--------+-----------+----------+-----------+
mysql> select count(*) from coronavirus; +----------+
+----------+
| count(*) |
+----------+
| 34783 |
+----------+
This shows the latest entry + the increase from the previous entry:
SELECT
cv.country,
cv.confirmed,
(cv.confirmed - (
SELECT
confirmed
FROM
coronavirus
WHERE
country = cv.country
AND id != cv.id
ORDER BY
updated DESC
LIMIT 1)) AS confirmed_increase
FROM
coronavirus cv
INNER JOIN (
SELECT
MAX(updated) AS updated,
country
FROM
coronavirus
GROUP BY
country) cv2 ON cv2.country = cv.country
AND cv.updated = cv2.updated
WHERE
cv.updated = cv2.updated;
What this does: As GROUP BY goes before ORDER BY we need to work around this first, so it fetches all entries and does a JOIN on itself to only fetch the latest entries for all countries. Then it uses a subquery to find the latest item of the same country which IS NOT the same ID as the latest entry, so that will be the forelast entry. Note that if you have other conditions for your query they need to be added to the subquery as well.