Mysql 为钙化日期时间差优化查询
我有一个SQL表:Mysql 为钙化日期时间差优化查询,mysql,sql,Mysql,Sql,我有一个SQL表: +---------+----------+---------------------+---------------------+---------+ | id | party_id | begintime | endtime | to_meas | +---------+----------+---------------------+---------------------+---------+ | 1395035
+---------+----------+---------------------+---------------------+---------+
| id | party_id | begintime | endtime | to_meas |
+---------+----------+---------------------+---------------------+---------+
| 1395035 | 9255 | 2010-09-26 00:34:02 | 2010-09-26 03:56:20 | 0 |
| 1395036 | 8974 | 2009-07-10 11:00:00 | 2009-07-10 21:30:00 | 0 |
| 1395037 | 8974 | 2009-07-10 23:14:00 | 2009-07-11 08:48:00 | 0 |
| 1395038 | 8975 | 2009-07-10 11:00:00 | 2009-07-10 21:30:00 | 0 |
| 1395039 | 8975 | 2009-07-10 23:14:00 | 2009-07-11 08:48:00 | 0 |
| 1395040 | 8974 | 2009-07-11 10:08:31 | 2009-07-12 18:49:51 | 0 |
| 1395041 | 8975 | 2009-07-11 10:08:31 | 2009-07-12 18:49:51 | 0 |
| 1395042 | 8974 | 2009-07-12 20:38:27 | 2009-07-13 20:33:21 | 0 |
| 1395043 | 8975 | 2009-07-12 20:38:27 | 2009-07-13 20:33:21 | 0 |
| 1395044 | 8974 | 2009-07-13 21:57:37 | 2009-07-15 08:25:45 | 0 |
| 1395045 | 8975 | 2009-07-13 21:57:37 | 2009-07-15 08:25:45 | 0 |
| 1395046 | 8974 | 2009-07-15 08:51:25 | 2009-07-16 10:29:13 | 0 |
| 1395047 | 8975 | 2009-07-15 08:51:25 | 2009-07-16 10:29:13 | 0 |
| 1395048 | 8974 | 2009-07-16 12:22:22 | 2009-07-17 14:39:10 | 0 |
| 1395049 | 8975 | 2009-07-16 12:22:22 | 2009-07-17 14:39:10 | 0 |
| 1395050 | 8976 | 2009-07-24 16:53:48 | 2009-07-25 08:47:29 | 0 |
| 1395051 | 8977 | 2009-07-24 16:53:48 | 2009-07-25 08:47:29 | 0 |
| 1395052 | 8978 | 2009-07-24 16:53:48 | 2009-07-25 08:47:29 | 0 |
| 1395053 | 8979 | 2009-07-24 16:53:48 | 2009-07-25 08:47:29 | 0 |
| 1395054 | 8976 | 2009-07-25 10:47:14 | 2009-07-26 09:41:44 | 0 |
+---------+----------+---------------------+---------------------+---------+
...
我需要计算begintime和previous endtime之间的时间,如果此差值大于30分钟,则将_meas设置为1。以下是我在MySQL中的尝试:
update doses d set to_meas=1 where d.id in
(select a.id from party join (select * from doses) a
on party_id=a.party_id
left join (select * from doses) b
on party.id=b.party_id
and b.begintime=(select min(begintime)
from (select * from doses) c
where c.begintime > a.endtime)
and timestampdiff(minute, a.endtime, b.begintime) > 30
group by party.id);
此命令准永久运行。我曾尝试在python的pandas中这样做:
最后一条语句大约运行10秒。有没有一种方法可以优化SQL代码,使其运行速度与pandas'one一样快?在MySQL 8.0中,您可以使用窗口函数选择想要的结果,如下所示:
select d.*,
(begintime > lag(endtime) over(partition by pary_id order by endtime) + interval 30 minute) as to_meas
from doses d
在早期版本中:
select d.*,
(
begintime > (
select max(endtime) + interval 30 minute
from doses d1
where d1.party_id = d.party_id and d1.endtime < d.endtime
)
) as to_meas
from doses d
在MySQL 8.0中,您可以通过窗口函数选择想要的结果,如下所示:
select d.*,
(begintime > lag(endtime) over(partition by pary_id order by endtime) + interval 30 minute) as to_meas
from doses d
在早期版本中:
select d.*,
(
begintime > (
select max(endtime) + interval 30 minute
from doses d1
where d1.party_id = d.party_id and d1.endtime < d.endtime
)
) as to_meas
from doses d
您可以使用exists更新数据,如下所示:
Update doses d
Set meas = 1
Where begintime > (select max(dd.endtime) + interval '30' minute
From doses dd where dd.begintime < d.begintime
And dd.party_id = d.party_id)
您可以使用exists更新数据,如下所示:
Update doses d
Set meas = 1
Where begintime > (select max(dd.endtime) + interval '30' minute
From doses dd where dd.begintime < d.begintime
And dd.party_id = d.party_id)
如果要更新数据,可以在更新中使用窗口函数: 然后,对于这个查询,您需要一个关于doseParty_id endtime的索引。我假设id已经声明为主键 注意:使用此索引,您可能会发现只需动态计算值比将其存储在表中更快 编辑: 在MySQL的旧版本中,您可以将其表述为:
update doses d join
(select d.*,
(select d2.endtime
from doses d2
where d2.party_id = d.party_id and
d2.endtime < d.endtime
) as prev_endtime
from doses d
) dd
on d.id = dd.id and
d.starttime > dd.prev_endtime + interval 30 minute
set to_meas = 1;
每个party_id的行数相对较少,因此相关查询似乎是合理的。这还需要一个关于party_id,endtime的索引。如果要更新数据,可以在更新中使用窗口功能: 然后,对于这个查询,您需要一个关于doseParty_id endtime的索引。我假设id已经声明为主键 注意:使用此索引,您可能会发现只需动态计算值比将其存储在表中更快 编辑: 在MySQL的旧版本中,您可以将其表述为:
update doses d join
(select d.*,
(select d2.endtime
from doses d2
where d2.party_id = d.party_id and
d2.endtime < d.endtime
) as prev_endtime
from doses d
) dd
on d.id = dd.id and
d.starttime > dd.prev_endtime + interval 30 minute
set to_meas = 1;
每个party_id的行数相对较少,因此相关查询似乎是合理的。这还需要一个关于party_id,endtime的索引。MySQL不支持在相关子查询中重新打开update语句的目标表,因此此查询引发语法错误:。这是MySQL更新语法的一个典型限制。@GMB这里应该和我一样:。。。From select*From dd…MySQL不支持在相关子查询中重新打开update语句的目标表,因此此查询引发语法错误:。这是MySQL更新语法的一个典型限制。@GMB这里应该和我一样:。。。从select*From DOVES dd…OP在我的回答中的某个点上评论说他们正在运行MySQL 5.7。但是这个评论被删除了。是的,我有5.7 OP在我的回答中的某个点上评论了他们运行的是MySQL 5.7。不过,该评论已被删除。是的,我有5.7