Я хочу видеть изменения в течение месяца за последние 3 месяца.
База данных:
MySQL:
SELECT DATE_FORMAT(CUR.time, '%Y %b') AS thisTime,
MAX(CUR.value) AS thisValue,
MAX(PRE.value) AS prevValue,
MAX(CUR.value)-MAX(PRE.value) AS compValue
FROM test CUR
INNER JOIN test PRE
ON MONTH(PRE.time) = (SELECT MAX(MONTH(XXX.time))
FROM test XXX
WHERE MONTH(XXX.time) < MONTH(CUR.time))
WHERE CUR.time > DATE_SUB(NOW(), INTERVAL 3 MONTH)
GROUP BY MONTH(CUR.time)
ORDER BY CUR.id
Результат:
Можно увидеть, что нет января!
Я хочу видеть изменения в течение месяца за последние 3 месяца, как это. У кого-нибудь есть идеи?
| 2019 Feb | 50 | 40 | 10 |
| 2019 Jan | 40 | 25 | 15 |
| 2018 Dec | 25 | 20 | 5 |
Проблема с попыткой использовать MONTH
в состоянии JOIN
заключается в переходе от 12 к 1 в конце года. Проще всего использовать дату в качестве строки YEARMONTH
:
SELECT DATE_FORMAT(t1.time, '%b %Y') AS thisTime,
MAX(t1.value) AS thisValue,
MAX(t2.value) AS prevValue,
MAX(t1.value) - MAX(t2.value) AS compValue
FROM test t1
JOIN test t2 ON DATE_FORMAT(t2.time, '%Y%m') = (SELECT MAX(DATE_FORMAT('time', '%Y%m'))
FROM test t3
WHERE DATE_FORMAT(t3.time, '%Y%m') < DATE_FORMAT(t1.time, '%Y%m'))
GROUP BY thisTime
ORDER BY STR_TO_DATE(CONCAT('1 ', thisTime), '%d %b %Y') DESC
Выход:
thisTime thisValue prevValue compValue
Feb 2019 50 40 10
Jan 2019 40 25 15
Dec 2018 25 20 5
Вместо того, чтобы пытаться выполнить сложное объединение, вы можете просто использовать подзапросы, поскольку таблица не очень сложна. Также просто отфильтруйте результаты 2-го числа каждого месяца, так как вам не нужно 1-е число из того, что показывает ожидаемый результат.
SELECT
DATE_FORMAT(cur.time,'%Y %b') AS thisTime,
cur.value AS thisValue,
(SELECT value FROM test WHERE time = DATE_SUB(cur.time,INTERVAL 1 MONTH)) AS prevValue,
(SELECT cur.value - value FROM test WHERE time = DATE_SUB(cur.time,INTERVAL 1 MONTH)) AS compValue
FROM
test AS cur
WHERE
cur.time >= DATE_SUB(CURDATE(),INTERVAL 3 MONTH)
AND DATE_FORMAT(cur.time,'%d') = 2
Результат:
thisTime thisValue prevValue compValue
2019 Feb 50 40 10
2019 Jan 40 25 15
2018 Dec 25 20 5
РЕДАКТИРОВАТЬ На точку Ник ниже, я предположил, что максимум всегда будет 2-го числа каждого месяца. Если это значение false и снимок таблицы просто не показывают месяц, в котором 1-е число было максимальным, то это изменение даст правильный максимальный результат.
JOIN
от monthMax
и обычная test
таблица гарантируют, что вы всегда получите максимальное значение за месяц, независимо от количества дат в этом месяце. Затем просто используйте тот же метод подзапроса, что и мой первоначальный запрос.
SELECT
DATE_FORMAT(t.time,'%Y %b') AS thisTime,
t.value AS thisValue,
(SELECT MAX(value) FROM test WHERE DATE_FORMAT(time,'%Y-%m') = DATE_FORMAT(DATE_SUB(t.time,INTERVAL 1 MONTH),'%Y-%m')) AS prevValue,
(SELECT t.value - MAX(value) FROM test WHERE DATE_FORMAT(time,'%Y-%m') = DATE_FORMAT(DATE_SUB(t.time,INTERVAL 1 MONTH),'%Y-%m')) AS compValue
FROM
(SELECT DATE_FORMAT(time,'%Y-%m') AS 'timeFix', MAX(value) AS 'maxValue' FROM test GROUP BY timeFix) AS monthMax
JOIN (test AS t) ON (monthMax.maxValue = t.value AND monthMax.timeFix = DATE_FORMAT(t.time,'%Y-%m'))
WHERE
t.time > DATE_SUB(CURDATE(),INTERVAL 3 MONTH)
Результат:
thisTime thisValue prevValue compValue
2019 Feb 50 40 10
2019 Jan 40 25 15
2018 Dec 25 20 5