Je dois avoir la base de la consommation sur la précédente par numéro SN ..__Ce sont mes données:
TABLE EnergyLog
SN Date Value
2380 2012-10-30 00:15:51 21.01
2380 2012-10-31 00:31:03 22.04
2380 2012-11-01 00:16:02 22.65
2380 2012-11-02 00:15:32 23.11
20100 2012-10-30 00:15:38 35.21
20100 2012-10-31 00:15:48 37.07
20100 2012-11-01 00:15:49 38.17
20100 2012-11-02 00:15:19 38.97
20103 2012-10-30 10:27:34 57.98
20103 2012-10-31 12:24:42 60.83
C'est le résultat dont j'ai besoin:
SN Date Value consumption
2380 2012-10-30 00:15:51 21.01 0
2380 2012-10-31 00:31:03 22.04 1.03
2380 2012-11-01 00:16:02 22.65 0.61
2380 2012-11-02 00:15:32 23.11 0.46
20100 2012-10-30 00:15:38 35.21 0
20100 2012-10-31 00:15:48 37.07 1.86
20100 2012-11-01 00:15:49 38.17 1.1
20100 2012-11-02 00:15:19 38.97 0.8
20103 2012-10-30 10:27:34 57.98 0
20103 2012-10-31 12:24:42 60.83 2.85
Travailler avec des variables MySQL est très bien, cela ressemble à des assignations de variables de programme en ligne. Tout d’abord, la clause FROM "déclare" les variables @ pour vous, vierges par défaut. Puis interrogez les enregistrements dans l'ordre souhaité. Il effectue un seul passage dans les données au lieu de passer par des sous-requêtes répétées, ce qui peut prendre beaucoup de temps.
Pour chaque ligne lue, comparez le @lastSN avec le SN de l'enregistrement en cours. Si différent, retournez toujours 0. Si IS est identique, calculez la différence simple. Une fois la comparaison effectuée, définissez @lastSN et @lastValue égaux à ceux de l'enregistrement en cours pour la comparaison des enregistrements suivants.
select
EL.SN,
EL.Date,
EL.Value, --remove duplicate alias
if( @lastSN = EL.SN, EL.Value - @lastValue, 0000.00 ) as Consumption,
@lastSN := EL.SN,
@lastValue := EL.Value
from
EnergyLog EL,
( select @lastSN := 0,
@lastValue := 0 ) SQLVars
order by
EL.SN,
EL.Date
Cela devrait faire l'affaire:
SELECT l.sn,
l.date,
l.value,
l.value - (SELECT value
FROM energylog x
WHERE x.date < l.date
AND x.sn = l.sn
ORDER BY date DESC
LIMIT 1) consumption
FROM energylog l;
Voir SQLFiddle: http://sqlfiddle.com/#!2/b9eb1/8
Une solution quasi universelle consiste à joindre les données sur elles-mêmes, à retrouver l'enregistrement précédent, en incluant une sous-requête corrélée dans la condition de jointure ...
SELECT
ThisLog.*,
COALESCE(ThisLog.Value - PrevLog.Value, 0) AS consumption
FROM
EnergyLog AS ThisLog
LEFT JOIN
EnergyLog AS PrevLog
ON PrevLog.SN = ThisLog.SN
AND PrevLog.Date = (SELECT MAX(Date)
FROM EnergyLog
WHERE SN = ThisLog.SN
AND Date < ThisLog.Date)
Cela fonctionne mieux avec un index couvrant à la fois (SN, Date)
.
Vous pouvez joindre deux lignes de la même table comme ceci:
SELECT this.*, prev.*
FROM tbl this
INNER JOIN tbl prev ON prev.id =
(
SELECT max(t.id)
FROM tbl t
WHERE t.id < this.id
)
WHERE ...
Votre cas ressemblera donc à:
SELECT this.SN, this.Date, this.Value, (this.Value - prev.Value) AS consumption
FROM EnergyLog this
INNER JOIN EnergyLog prev ON prev.Date =
(
SELECT max(t.Date)
FROM EnergyLog t
WHERE t.Date < this.Date
)
Pouvez-vous s'il vous plaît essayer la requête ci-dessous une fois.
SELECT e1.*,
(SELECT Value
FROM EnergyLog e2
WHERE e2.sn = e1.sn AND e2.date < e1.date
ORDER BY date DESC
LIMIT 1)-l.Value consumption
FROM EnergyLog e1;