我有一张包含三列timestamp
,sensor_id
和value
的表格。类似的东西:
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的解决方案正在发挥作用 - 非常感谢:)
答案 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