0

I have a table MeterReading in mysql and it has the following columns

meterid bigint(4),
reading bigint(4),
date date,
time time,
consumption,
primary key(meterid,reading)

i am inserting the vlues to this table except consumption and my problem is how to update the table based on these values.

i tried the following query

update MeterReading a 
set consumption=(select reading-IFNULL((select MAX(reading) from MeterReading  where meterid=a.meterid AND (date < a.date OR date = a.date AND time < a.time )),0));

i want the result like:

  meterid | reading | date       | time     | consumption |
+---------+---------+------------+----------+-------------+
|       1 |     450 | 2012-10-05 | 06:05:05 |        450  |
|       1 |     550 | 2012-10-06 | 08:05:05 |        100  |
|       1 |     600 | 2012-10-07 | 09:05:05 |        50   |
|       1 |     700 | 2012-10-08 | 10:05:05 |        100  |

please help me

4

1 回答 1

1

试试这个:

UPDATE MeterReading a 
LEFT JOIN
(
  SELECT meterid, MAX(reading) MaxReading
  FROM MeterReading
  GROUP BY meterid
) g ON g.meterid = a.meterid
SET a.consumption = IFNULL(g.MaxReading, 0) - a.reading ;

更新:使用IFNULL(g.MaxReading, 0) - a.reading或者您可以使用ABS(IFNULL(g.MaxReading, 0) - a.reading).

SQL 小提琴演示


编辑:因此,您需要使用当前读数值与下一行读数值之间的差异来更新每个复合键 ( meterid, reading) 的consumption值。如果是这样,您可以这样做:

UPDATE MeterReading m
INNER JOIN
(
  SELECT 
    m.*,
    @rownum := @rownum + 1 AS rank
  FROM meterreading m, (SELECT @rownum := 0) r
  ORDER BY m.date 
) t1  ON m.meterid = t1.meterid 
     AND m.reading = t1.reading
LEFT JOIN 
(
  SELECT 
    m.*,
    @rownum2 := @rownum2 + 1 AS rank
  FROM meterreading m, (SELECT @rownum2 := 0) r
  ORDER BY m.date 
) t2  ON  t1.rank - t2.rank = 1
SET m.consumption = (t1.reading - IFNULL(t2.reading, 0));

更新的 SQL Fiddle 演示

这将使您的表meterreading在更新后看起来像:

| METERID | READING |                           DATE |                           TIME | CONSUMPTION |
-----------------------------------------------------------------------------------------------------
|       1 |     450 | October, 05 2012 02:00:00+0000 | January, 01 1970 06:05:05+0000 |         450 |
|       1 |     550 | October, 06 2012 02:00:00+0000 | January, 01 1970 08:05:05+0000 |         100 |
|       1 |     600 | October, 07 2012 02:00:00+0000 | January, 01 1970 09:05:05+0000 |          50 |
|       1 |     700 | October, 08 2012 02:00:00+0000 | January, 01 1970 10:05:05+0000 |         100 |

注意:我使用@rownum变量来获取每一行的排名,问题是,这个排名是基于Date列的顺序,所以它会得到下一个日期的读数值。

于 2013-01-03T09:57:59.610 回答