我在MySQL-Server(InnoDB)上有两个表。 两者都有一个datetime-field,每行包含一个测量值。 表A中的测量每分钟进行一次,表B中的测量每秒进行一次。
现在我想选择表B中测量的Min(),在表A中测量时间为+/- 30秒,并用表A中的测量结果显示。
当我查找EQUAL时间码时,查询将在大约一秒钟内完成。
但是当我尝试用以下语句选择它们时:
SELECT min(tableB.measurement),tableA.*
FROM tableA,tableB
WHERE tableA.timecode BETWEEN DATE_SUB(tableB.timecode,INTERVAL 30 SECOND) and DATE_ADD(tableB.timecode,INTERVAL 30 SECOND)
GROUP BY tableA.timecode;
然后查询将永远运行(或者至少直到它达到MySQL Workbench的超时时间,我将其设置为超过一小时)
所以数据的结果如
table A
|timecode|measurement|
|15:00:30| 5 |
|15:10:30| 6 |
table B
|timecode|measurement|
|15:00:29| 105 |
|15:00:31| 56 |
|15:10:28| 25 |
|15:10:32| 16 |
应该导致s.th喜欢
|min(tableB.measurement)| timecode | measurement|
| 56 | 15:00:30 | 5 |
| 16 | 15:10:30 | 6 |
我实际上误用了SQL来处理大量的表格数据(我可能不会改变)。我知道这不是你应该做的,但我发现没有其他选择来应对这个1500万行数据集...... 两个datetime-fields都有一个索引BTW ...
希望得到帮助, 罗伯特
这里是建议查询的EXPLAIN:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY a ALL 125953 100.00
2 DEPENDENT SUBQUERY b ALL idx_xc_timecode_trans,idx_xc_timecode_trans_measurement 15755656 11.11
Range checked for each record (index map: 0x60)
更新: SQL Workbench中的visual EXPLAIN只显示了s.th的成本,如
select * where tableA.timecode = tableB.timecode
是~160.000
而sth喜欢
select * where tableA.timecode between DATE_SUB( tableB.timecode, interval 30 second) and DATE_ADD(tableB.timecode, interval 30 second)
是~99.600.000.000 !!!
这是否意味着这可能是不可行的任务?这是一个不常见的"查询(根据"这不是DBMS的用途")
答案 0 :(得分:0)
只要tableB.measurement
被编入索引,就可以使用以下查询:
SELECT (
SELECT b.measurement
FROM tableB b
WHERE b.timecode BETWEEN a.timecode - INTERVAL 30 SECOND
AND a.timecode + INTERVAL 30 SECOND
ORDER BY b.timecode
LIMIT 1
) AS MinB,
a.timecode,
a.measurement
FROM tableA a
/*GROUP BY a.timecode*/
您希望MIN(b.measurement)
而不是MIN(b.timecode)
,因此可以简化查询:
SELECT (
SELECT MIN(b.measurement)
FROM tableB b
WHERE b.timecode BETWEEN a.timecode - INTERVAL 30 SECOND
AND a.timecode + INTERVAL 30 SECOND
) AS MinB,
a.timecode,
a.measurement
FROM tableA a
答案 1 :(得分:0)
您在TableB中添加或减去时间码datetime值,但未指定INTERVAL。
SELECT min(tableB.timecode),tableA.*
FROM tableA,tableB
WHERE tableA.timecode < DATE_ADD(tableB.timecode, + INTERVAL 30 SECOND) and tableA.timecode > DATE_ADD(tableB.timecode, INTERVAL -30 SECOND);
答案 2 :(得分:0)
无法对此进行测试,但是将时间码四舍五入到子查询中的最近分钟,并且仅加入时间码可能会很好地执行:
SELECT b.measurement,tableA.*
FROM tableA a
JOIN (SELECT SEC_TO_TIME((ROUND(TIME_TO_SEC(timecode)/60)) * 60 as timecode
,MIN(measurement) as measurement
FROM tableB
GROUP BY SEC_TO_TIME((ROUND(TIME_TO_SEC(timecode)/60)) * 60
)b
ON a.timecode = b.timecode
由于舍入不会,您可以查看TIMESTAMPDIFF(second,a.timecode,b.timecode)
的效果是否优于当前加入:
SELECT min(b.measurement),a.timecode,a.measurement
FROM tableA a
JOIN tableB b
ON ABS(TIMESTAMPDIFF(second,a.timecode,b.timecode)) < 30
GROUP BY a.timecode,a.measurement;