MySQL读取,计算和回写

时间:2014-04-02 12:23:27

标签: php python mysql

我需要一些MySQL命令的帮助。

我的MySQL表看起来像这样

    mysql> DESCRIBE sensor_readout;
+-----------+-----------+------+-----+---------------------+-------+
| Field     | Type      | Null | Key | Default             | Extra |
+-----------+-----------+------+-----+---------------------+-------+
| timestamp | timestamp | NO   |     | 0000-00-00 00:00:00 |       |
| sensor_id | char(2)   | NO   | PRI | NULL                |       |
| volume    | int(4)    | NO   | PRI | NULL                |       |
+-----------+-----------+------+-----+---------------------+-------+

我当前存储的数据(正在更新音量变化)是

mysql> SELECT * FROM sensor_readout;
+---------------------+-----------+--------+
| timestamp           | sensor_id | volume |
+---------------------+-----------+--------+
| 2014-04-01 11:27:16 | 22        |   3327 |
| 2014-04-01 12:44:00 | 22        |   3328 |
| 2014-04-01 11:27:13 | 23        |   2643 |
| 2014-04-01 11:54:44 | 23        |   2644 |
| 2014-04-01 11:27:14 | 24        |   3407 |
| 2014-04-01 11:55:03 | 24        |   3408 |
+---------------------+-----------+--------+

我想做的是每当脚本运行时(我猜python但欢迎任何其他脚本建议),脚本将在传感器id 22,23和24上获取最后一个音量记录(按时间戳记)。执行数学计算在22和23卷。

然后将数据写回表格" poraba"。 22 + 23代表" voda_mrzla"。 24将是voda_topla。随着进入数据库的日期和月份(不需要时间)。

mysql> DESCRIBE poraba;
+------------+------------+------+-----+---------+-------+
| Field      | Type       | Null | Key | Default | Extra |
+------------+------------+------+-----+---------+-------+
| mesec      | date       | NO   |     | NULL    |       |
| voda_mrzla | varchar(5) | NO   |     | NULL    |       |
| voda_topla | varchar(5) | NO   |     | NULL    |       |
+------------+------------+------+-----+---------+-------+ 

现在我尝试使用以下python脚本(见下文)。但我被困在那里。我唯一能做的就是从每个sensor_id上的最后一个值创建读数

import MySQLdb

#establish connection to MySQL. You'll have to change this for your database.
conn = MySQLdb.connect('localhost', '*****', '****', 'moteino') 

cursor=conn.cursor()



sql = """SELECT sensor_id, volume 
         FROM sensor_readout 
         WHERE sensor_id = 22  
         ORDER BY timestamp DESC LIMIT 1"""

sql1 = """SELECT sensor_id, volume 
         FROM sensor_readout 
         WHERE sensor_id = 23 
         ORDER BY timestamp DESC LIMIT 1"""

sql2 = """SELECT sensor_id, volume 
         FROM sensor_readout 
         WHERE sensor_id = 24 
         ORDER BY timestamp DESC LIMIT 1"""

cursor.execute(sql1)
data1=cursor.fetchall()

cursor.execute(sql2)
data2=cursor.fetchall()

cursor.execute(sql)
data=cursor.fetchall()


print(data, data1, data2)

打印输出是这样的

((('22', 3331L),), (('23', 2647L),), (('24', 3412L),))

UPDATE !!!!

甜蜜的家伙以下代码就像我想要的那样工作。我确实用time_recorded更改了时间戳,因此最小化时间戳混淆。

    -- Direct insert into DDBB
INSERT INTO poraba ( voda_mrzla, voda_topla )

  -- Get the values, with the right operations
  SELECT
    SUM( IF(sensor_id = 22 OR sensor_id = 23, volume, 0 ) ) voda_mrzla
  , SUM( IF ( sensor_id = 24, volume, 0 ) ) voda_topla
  FROM ( 
  -- Get only the values with max timestamp for each sensor
  SELECT s.`time_recorded`, s.sensor_id, s.volume
  FROM sensor_readout s
  INNER JOIN (
      SELECT sensor_id, MAX(`time_recorded`) mts
      FROM sensor_readout
      GROUP BY sensor_id
  ) maxS
  ON ( s.`time_recorded` = maxS.mts AND s.sensor_id = maxS.sensor_id )
  ) maxTime

我还有另外一个问题。我想要实现的最后一步是脚本从前一个月和当前月份获取值并创建减去计算。这将代表一个月的冷热水使用。抱歉eng / slo措辞mash-up(冷是voda_mrzla,热是voda_topla)

       mysql> DESCRIBE usage_per_month;
+-----------------+-------------+------+-----+---------+-------+
| Field           | Type        | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| difference_cold | varchar(10) | NO   |     | NULL    |       |
| difference_hot  | varchar(10) | NO   |     | NULL    |       |
+-----------------+-------------+------+-----+---------+-------+

Mybe这个表更容易选择以前的值

mysql> SELECT * FROM poraba;
+---------------------+------------+------------+-----------+
| mesec               | voda_mrzla | voda_topla | id_poraba |
+---------------------+------------+------------+-----------+
| 2014-03-03 16:19:08 | 5985       | 3417       |         1 |
| 2014-04-03 20:57:51 | 5978       | 3412       |         2 |

2 个答案:

答案 0 :(得分:0)

使用纯MySQL查询,将更容易,更快:请UPDATESELECT一起使用。

MySQL - UPDATE query based on SELECT Query

修改

我误解了您的问题,在您的情况下,您应该INSERT使用SELECT,:P

INSERT with SELECT

好的,我有更多时间享受这个,XD:

-- Direct insert into DDBB
INSERT INTO poraba ( voda_mrzla, voda_topla )

  -- Get the values, with the right operations
  SELECT
    SUM( IF(sensor_id = 22 OR sensor_id = 23, volume, 0 ) ) voda_mrzla
  , SUM( IF ( sensor_id = 24, volume, 0 ) ) voda_topla
  FROM ( 
  -- Get only the values with max timestamp for each sensor
  SELECT s.`timestamp`, s.sensor_id, s.volume
  FROM sensor_readout s
  INNER JOIN (
      SELECT sensor_id, MAX(`timestamp`) mts
      FROM sensor_readout
      GROUP BY sensor_id
  ) maxS
  ON ( s.`timestamp` = maxS.mts AND s.sensor_id = maxS.sensor_id )
  ) maxTime

您可以查看此sqlfiddle中的选择结果:http://sqlfiddle.com/#!2/67e65/1

您的表存在一些表结构差异,以便我们轻松插入时间戳:我设置了默认时间戳CURRENT_TIMESTAMP,因此任何添加的行都将获得当前时间。正如您所看到的,使用此查询,您可以直接从数据库插入而无需更多脚本计算。 sumif仅用于从SELECT最大值查询中获取的三行中的正确值(请在SQL Select only rows with Max Value on a Column中查看有关此问题的更多信息)。

之后,您的脚本只需运行此查询,您就可以在表格中获取新数据,随时可以选择XD。很抱歉没有在你的Pyton脚本中编写整个代码,我来自PHP并且不想搞砸它。

答案 1 :(得分:0)

在您喜欢的任何脚本中尝试此查询:

INSERT INTO poraba
SET voda_mrzla = (
    SELECT volume 
    FROM sensor_readout 
    WHERE sensor_id = 22  
    ORDER BY `timestamp` DESC LIMIT 1
) + (
    SELECT volume 
    FROM sensor_readout 
    WHERE sensor_id = 23  
    ORDER BY `timestamp` DESC LIMIT 1
),
voda_topla = (
    SELECT volume 
    FROM sensor_readout 
    WHERE sensor_id = 24
    ORDER BY `timestamp` DESC LIMIT 1
),
`date` = (
    SELECT `timestamp`
    FROM sensor_readout 
    ORDER BY `timestamp` DESC LIMIT 1
)