35

SN番号ごとに、以前のものに基づいて消費値を取得する必要があります。これは私のデータです:

表 エネルギーログ

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

これは私が必要とする結果です:

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
4

5 に答える 5

81

MySQL変数の操作は、インラインプログラム変数の割り当てのように素晴らしいです。まず、FROM句は@変数を「宣言」し、デフォルトで空白になります。次に、必要な順序でレコードをクエリします。時間がかかる可能性のあるサブクエリを繰り返す代わりに、データを1回通過します。

読み取られた行ごとに、@lastSNを現在のレコードのSNと比較します。異なる場合は、常に0を返します。同じである場合は、単純な差を計算します。比較が行われた後でのみ、@ lastSNと@lastValueを、次のレコード比較のために現在のレコードと同じに設定します。

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
于 2012-11-02T13:39:45.740 に答える
15

これでうまくいくはずです:

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;

SQLFiddle を参照してください: http://sqlfiddle.com/#!2/b9eb1/8

于 2012-11-02T13:37:36.287 に答える
13

ほぼ普遍的な解決策は、データをそれ自体に結合し、結合条件に相関サブクエリを含めることによって、前のレコードを見つけることです...

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)

これは、両方をカバーする1つのインデックスで最高のパフォーマンスを発揮します(SN, Date)

于 2012-11-02T13:39:50.577 に答える
0

以下のクエリを一度試してみてください。

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;
于 2012-11-02T14:08:02.673 に答える