У меня есть этот запрос, который занимает 0.04 секунды для загрузки
SELECT sg.Name AS 'Customer Name',
m.meter_id AS 'Serial No',
DATE_FORMAT(datetime, '%Y/%m/%d') AS Date,
MAX(wh_total) AS Present
FROM meter_data m
INNER JOIN enrollment e
ON e.Meter_Id = m.meter_id AND e.Status = 1
INNER JOIN company_subgroup sg
ON sg.Id = e.Subgroup_Id
INNER JOIN company_group g
ON g.Id = sg.Group_Id
WHERE date(dateTime) BETWEEN '2018/06/01' AND '2018/06/30'
AND m.meter_id = '12345'
AND m.wh_total < 1000000000
GROUP BY date(datetime)
Но если я добавил этот столбец "Предыдущий", для выполнения потребуется около 20 секунд.
SELECT sg.Name AS 'Customer Name',
m.meter_id AS 'Serial No',
DATE_FORMAT(datetime, '%Y/%m/%d') AS Date,
// THIS (main issue)
COALESCE((SELECT MAX(wh_total) FROM meter_data WHERE date(dateTime) < date(m.dateTime) AND meter_id = '12345'
AND wh_total < 1000000000 GROUP BY date(dateTime) ORDER BY date(dateTime) DESC LIMIT 1),0) AS Previous,
//
MAX(wh_total) AS Present,
// THIS (But I guess this does not affect the query that much since it only substract the two columns)
ROUND(MAX(wh_total) - MIN((SELECT Previous)),2) AS Consumption
//
FROM meter_data m
INNER JOIN enrollment e
ON e.Meter_Id = m.meter_id AND e.Status = 1
INNER JOIN company_subgroup sg
ON sg.Id = e.Subgroup_Id
INNER JOIN company_group g
ON g.Id = sg.Group_Id
WHERE date(dateTime) BETWEEN '2018/06/01' AND '2018/06/30'
AND m.meter_id = '12345'
AND m.wh_total < 1000000000
GROUP BY date(datetime)
В основном, столбец Previous получает данные предыдущей строки. Запрос выглядит примерно так:
Customer Name | Serial No | Date | Previous | Present | Consumption
ABC | 12345 | 06/01/2018 | 0 | 1 | 1
ABC | 12345 | 06/02/2018 | 1 | 3 | 2
ABC | 12345 | 06/03/2018 | 3 | 8 | 5
ABC | 12345 | 06/04/2018 | 8 | 10 | 2
Я попытался использовать LAG (столбец) для получения данных предыдущих строк, к сожалению, версия MySQL - 5.6. Есть ли способ оптимизировать этот запрос?
Попробуйте этот запрос. это сохранение предыдущих данных в пользователе var.
Я изменил его снова. Функция MAX получила ошибку. поэтому я поставил его в подзапрос.
SELECT r.'Customer NAME', r.'SERIAL NO', r.'DATE' , @prev AS Previous , @reav := r.'Present'
FROM (
SELECT sg.Name AS 'Customer NAME',
m.meter_id AS 'SERIAL NO',
DATE_FORMAT(DATETIME, '%Y/%m/%d') AS 'DATE',
MAX(wh_total) AS 'Present'
FROM meter_data m
INNER JOIN enrollment e
ON e.Meter_Id = m.meter_id AND e.Status = 1
INNER JOIN company_subgroup sg
ON sg.Id = e.Subgroup_Id
INNER JOIN company_group g
ON g.Id = sg.Group_Id
WHERE DATE(DATETIME) BETWEEN '2018/06/01' AND '2018/06/30'
AND m.meter_id = '12345'
AND m.wh_total < 1000000000
GROUP BY DATE(DATETIME)
) AS r
CROSS JOIN (SELECT @prev:=0) AS INIT;
Попробуй это
SELECT sg.Name AS 'Customer Name',
m.meter_id AS 'Serial No',
DATE_FORMAT(datetime, '%Y/%m/%d') AS Date,
COALESCE(mx.max_total,0) AS Previous,
MAX(wh_total) AS Present,
ROUND(MAX(wh_total) - MIN((mx.max_total)),2) AS Consumption
FROM meter_data m
INNER JOIN enrollment e ON e.Meter_Id = m.meter_id AND e.Status = 1
INNER JOIN company_subgroup sg ON sg.Id = e.Subgroup_Id
INNER JOIN company_group g ON g.Id = sg.Group_Id
LEFT JOIN (SELECT date(dateTime) as dt, MAX(wh_total) max_total
FROM meter_data
WHERE meter_id = '12345' AND wh_total < 1000000000
GROUP BY date(dateTime)) mx on mx.dt < date(m.dateTime)
WHERE date(m.dateTime) BETWEEN '2018/06/01' AND '2018/06/30'
AND m.meter_id = '12345'
AND m.wh_total < 1000000000
GROUP BY date(m.datetime)
Примечание: если эта строка возвращает более одной строки, то ограничивайте это, добавив еще некоторое условие