实际表格包含电表的处理数据,我是在每小时处理数据并将其插入processed_data_hourly
表格后,在余下的基础上从中采样的电表。
现在我要做的是根据客户选择的日期和时间段显示报告processed_data_hourly
表
下面的查询给出了我想要的预期输出,但是执行大约70到90秒需要花费很多时间。
所以任何人都可以帮我优化这个查询,以便执行时间更短
Query :
SELECT
A.node_id,
A.start_time,
B.end_time,
A.startReadingIMP,
B.endReadingIMP,
(B.endReadingIMP - A.startReadingIMP) diffIMP
FROM
((SELECT
node_id, start_time, end_time, srv_vah startReadingIMP
FROM
processed_data_hourly
WHERE
start_time >= '2017-05-15 00:00:00'
AND end_time <= '2017-05-15 23:59:59'
GROUP BY node_id
ORDER BY start_time ASC) AS A, (SELECT
node_id, start_time, end_time, erv_vah endReadingIMP
FROM
processed_data_hourly
WHERE
start_time >= '2017-05-15 00:00:00'
AND end_time <= '2017-05-15 23:59:59'
GROUP BY end_time DESC) AS B
)
WHERE
A.node_id = 6 and B.node_id=6
GROUP BY A.node_id , B.node_id
表格结构
P.S:表格结构太大而无法发布,因为它包含大量列
答案 0 :(得分:0)
首先,您的查询中存在语法错误:
WHERE
start_time >= '2017-05-15 00:00:00'
AND end_time <= '2017-05-15 23:59:59'
GROUP BY end_time DESC) AS B
)
不允许DESC
列表之后的group by
子句。
我想它应该是GROUP BY node_id ORDER BY end_time DESC
。
如果我的问题是正确的,那么我的第二句话是您的查询使用MySQL Group by extenstion。根据文件:
如果禁用ONLY_FULL_GROUP_BY,则为标准的MySQL扩展 GROUP BY的SQL使用允许选择列表,HAVING条件或 ORDER BY列表引用非聚合列,即使列 在功能上不依赖于GROUP BY列。这会导致MySQL 接受前面的查询。在这种情况下,服务器是免费的 从每个组中选择任何值,所以除非它们相同,否则 选择的值是不确定的,这可能不是你想要的。 此外,不能从每个组中选择值 受添加ORDER BY子句影响。结果集排序发生 选择值后,ORDER BY不会影响哪个 服务器选择的每个组中的值。禁用 ONLY_FULL_GROUP_BY主要是因为有些人知道这一点 数据的属性,每个非聚合列中的所有值都不是 在GROUP BY中命名的每个组都是相同的。
有人可能会说,实际上你的查询是从表中挑选随机行 您可以在这个简单的演示中观察到:SQLFiddle
SELECT * FROM processed_data_hourly;
| node_id | start_time | end_time | srv_vah | erv_vah |
|---------|----------------------|----------------------|---------|---------|
| 6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z | 11 | 111 |
| 6 | 2017-05-15T00:05:00Z | 2017-05-15T00:12:00Z | 22 | 222 |
| 6 | 2017-05-15T00:04:00Z | 2017-05-15T00:13:00Z | 33 | 333 |
| 6 | 2017-05-15T00:07:00Z | 2017-05-15T00:10:00Z | 44 | 444 |
| 6 | 2017-05-15T00:08:00Z | 2017-05-15T00:21:00Z | 55 | 555 |
SELECT
A.node_id,
A.start_time,
B.end_time,
A.startReadingIMP,
B.endReadingIMP,
(B.endReadingIMP - A.startReadingIMP) diffIMP
FROM
((SELECT
node_id, start_time, end_time, srv_vah startReadingIMP
FROM
processed_data_hourly
WHERE
start_time >= '2017-05-15 00:00:00'
AND end_time <= '2017-05-15 23:59:59'
GROUP BY node_id
ORDER BY start_time ASC) AS A, (SELECT
node_id, start_time, end_time, erv_vah endReadingIMP
FROM
processed_data_hourly
WHERE
start_time >= '2017-05-15 00:00:00'
AND end_time <= '2017-05-15 23:59:59'
GROUP BY node_id
ORDER BY end_time DESC) AS B
)
WHERE
A.node_id = 6 and B.node_id=6
GROUP BY A.node_id , B.node_id
| node_id | start_time | end_time | startReadingIMP | endReadingIMP | diffIMP |
|---------|----------------------|----------------------|-----------------|---------------|---------|
| 6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z | 11 | 111 | 100 |
如果你分析上面的结果,你可以看到两个子查询都选择了第一行,即:
| node_id | start_time | end_time | srv_vah | erv_vah |
|---------|----------------------|----------------------|---------|---------|
| 6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z | 11 | 111 |
如果这确实是您想要的结果,您可以将查询重写为另一个按id, start_time
对表格进行排序的查询,并为每个id
选择第一行,例如:
SELECT node_id,
start_time,
end_time,
srv_vah As startReadingIMP,
erv_vah As endReadingIMP,
erv_vah - srv_vah As diffIMP
FROM processed_data_hourly a
WHERE NOT EXISTS (
SELECT *
FROM processed_data_hourly b
WHERE a.node_id = b.node_id
AND b.start_time < a.start_time
);
| node_id | start_time | end_time | startReadingIMP | endReadingIMP | diffIMP |
|---------|----------------------|----------------------|-----------------|---------------|---------|
| 6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z | 11 | 111 | 100 |
演示:http://sqlfiddle.com/#!9/8faefc/5
接下来,如果您在node_id, start_time
上添加索引,那么此查询应该非常快。