使用不同数量的变量进行查询

时间:2014-06-18 21:37:45

标签: python mysql

我有一张包含三列timestampsensor_idvalue的表格。类似的东西:

timestamp1,sensor1,value1
timestamp1,sensor2,value2
timestamp1,sensor3,value3
...
timestamp2,sensor1,value1
timestamp2,sensor2,value2
timestamp2,sensor3,value3
...

现在我需要以下列格式将此表的内容写入文本文件:

timestamp1,value1,value2,value3,...
timestamp2,value1,value2,value3,...

用户选择应写入文件的时间范围和传感器。因此传感器的数量各不相同。我想在这段时间内获取所有传感器的值最简单,并从python中的非选定传感器中删除它们。

这是正确的还是可以指定具有不同变量量的查询?

我是否可以立即提出一个查询,该查询会立即显示指定的格式(列出sensor_id后面timestamp的相同时间戳的所有值)?

我正在使用mysql.connector

更新

sensor_clause = ','.join(selected_sensors)
query = """
        SELECT timestamp, group_concat(value) FROM measurements
        WHERE sensor_id in (%s) AND timestamp BETWEEN %s AND %s GROUP BY
        timestamp ORDER BY timestamp
        """
cursor.execute(query, (sensor_clause, start, stop))
data = cursor.fetchall()
print(cursor._executed)  

查询中的结果:

"SELECT timestamp, group_concat(value) FROM measurements WHERE sensor_id in ('1,2,4,5') AND timestamp BETWEEN '2014-04-01' AND '2014-06-22' GROUP BY timestamp ORDER BY timestamp"

并给出结果:

[(datetime.datetime(2014, 4, 1, 0, 0), '-1.736'), (date....

在固定查询中用('1,2,4,5')替换('1','2','4','5')会得到所需的结果:

[(datetime.datetime(2014, 4, 1, 0, 0), '-1.736,-1.375,6.843,7.87'), (date...

所以现在关于让sensor_clause正确格式化......

更新2

Ashalynd的解决方案正在发挥作用 - 非常感谢:)

3 个答案:

答案 0 :(得分:1)

这个怎么样?

sensors = get_sensors()  #assume you have a method that returns a list
sensor_clause = ','.join(sensors) # if sensor_ids are numbers
OR
sensor_clause = "'"+ "','".join(sensors)+"'" # if sensor_ids are text values
# the result will look like 'sensor1','sensor2','sensor3'
timestamp_clause = get_timestamp_clause() #e.g. 'timestamp between <day1> and <day2>' etc

query = """SELECT timestamp, group_concat(value order by sensor_id) 
FROM <yourtable> WHERE sensor_id in (%s) 
AND %s GROUP BY timestamp ORDER BY timestamp""" % ( sensor_clause, timestamp_clause )

order by中的group_concat子句确保值以相同的顺序列出)

生成的查询将如下所示:

SELECT timestamp, group_concat(value order by sensor_id) 
FROM <yourtable> WHERE sensor_id in (sensor1, sensor2, sensor3)
AND <timeclause> GROUP BY timestamp ORDER BY timestamp;

此查询将为您提供一个包含条目的列表,然后您可以将其输出到您喜欢的任何位置。

如果要检查实际选择了哪些传感器ID,可以执行

SELECT timestamp, group_concat(concat_ws(',', sensor, value) order by sensor_id) 
FROM <yourtable>
WHERE sensor in (sensor1, sensor2, ....)
GROUP BY timestamp

这会给你类似的东西:

dd-mm-yyyy, "sensor1,value1,sensor2,value2"
dd-mm-yyyy, "sensor1,value1,sensor2,value2,sensor3,value3"

(假设例如在第一个时间戳上只有2个传感器产生值)

然后您可以在Python代码中进一步处理这些数据。

具体而言,关于OP:

sensor_clause = ','.join(selected_sensors)
query = """
        SELECT timestamp, group_concat(value order by sensor_id) FROM measurements
        WHERE sensor_id in (%s) AND timestamp BETWEEN '%s' AND '%s'
        GROUP BY timestamp ORDER BY timestamp
        """ % (sensor_clause, start, stop)
cursor.execute(query)
data = cursor.fetchall()
print(cursor._executed)  

为什么OP版本不起作用:原因是sensor_clause不是一个参数,它是一个序列。它不能作为一个参数发送(否则它将被解释为字符串)。

更新:解决丢失的传感器值的另一种方法是创建一个小表,其中包含传感器的所有可能值并与其进行左连接,这将使缺失值显示为NULL,例如:

(假设这个小表称为传感器,它有一列,sensor_id)

query = """
            SELECT timestamp, group_concat(value order by s.sensor_id) 
            FROM  measurements m LEFT JOIN sensors s 
            ON m.sensor_id=s.sensor_id
            WHERE s.sensor_id in (%s) AND timestamp BETWEEN '%s' AND '%s'
            GROUP BY timestamp ORDER BY timestamp
            """ % (sensor_clause, start, stop)

答案 1 :(得分:0)

select timestamp, 
case when sensor = sensor1 then value1 end as value1,
case when sensor =sensor2 then value2 end as value2,
case when sensor =sensor3 then value3 end as value3

from table 

怎么样?

答案 2 :(得分:0)

如果你知道传感器的数量,你可以从这样的事情开始:

SELECT timestamp, 
       MAX(sensor1) AS sensor1,
       MAX(sensor2) AS sensor2,
       MAX(sensor3) AS sensor3
FROM (
  SELECT timestamp, value AS sensor1, 0 AS sensor2, 0 AS sensor3 
    FROM datatable WHERE sensor='sensor1'
  UNION
  SELECT timestamp, 0 AS sensor1, sensor AS sensor2, 0 AS sensor3 
    FROM datatable WHERE sensor='sensor2'
  UNION
  SELECT timestamp, 0 AS sensor1, 0 AS sensor2, sensor AS sensor3 
    FROM datatable WHERE sensor='sensor3'
)Q1
GROUP BY timestamp
ORDER BY timestamp