具有多个类似子选择的mysql update命令

时间:2011-01-14 23:47:09

标签: sql mysql

我编写了以下UPDATE命令,但子选择中存在冗余。我不是SQL专家,非常感谢帮助提高查询效率。提前谢谢。

update trips
  set origin = 
  (select stop_name 
    from stops 
    inner join stop_times
    on stops.stop_id = stop_times.stop_id
    where stop_times.trip_id = trips.trip_id
    order by stop_sequence asc
    limit 1) 
  ,
  destination = 
  (select stop_name 
    from stops 
    inner join stop_times
    on stops.stop_id = stop_times.stop_id
    where stop_times.trip_id = trips.trip_id
    order by stop_sequence desc
    limit 1)
  ,
  starts = 
  (select arrival_time
    from stop_times
    where stop_times.trip_id = trips.trip_id
    order by stop_sequence asc
    limit 1) 
  ,
  ends = 
  (select arrival_time
    from stop_times
    where stop_times.trip_id = trips.trip_id
    order by stop_sequence desc
    limit 1)
;

以下是相关的表格定义。大约有72K 旅行,8K站,200万停止时间。也许平均20?停止 每次旅行(只是猜测)。

create table stop_times (
  trip_id varchar(255),
  arrival_time time,
  stop_id varchar(255),
  stop_sequence int unsigned,
) type=MyISAM;

alter table stop_times add index stop_id (stop_id(5));
alter table stop_times add index trip_id (trip_id(5));

create table stops (
  stop_id varchar(255),
  stop_name varchar(255),
  stop_lat float,
  stop_lon float,
  primary key (stop_id)
) type=MyISAM;

create table trips (
  route_id varchar(255),
  trip_id varchar(255), /* primary key is here */
  /* denormalized fields */
  origin varchar(255),
  destination varchar(255),
  starts time,
  ends time,
  primary key(trip_id)
) type=MyISAM;
alter table trips add index route_id (route_id(5));

1 个答案:

答案 0 :(得分:1)

首先在stop_times上添加一个索引,以包含trip_id和stop_sequence列

ALTER TABLE stop_times ADD PRIMARY KEY(trip_id, stop_sequence)

然后,尝试运行此更新:

update trips t JOIN (
    SELECT trip_id, MIN(stop_sequence) minS, MAX(stop_sequence) maxS 
    FROM stop_times
    GROUP BY trip_id
) tg ON t.trip_id = tg.trip_id
JOIN stop_times stFirst ON tg.trip_id = stFirst.trip_id AND stFirst.stop_sequence = tg.minS
JOIN stop_times stLast ON tg.trip_id = stLast.trip_id AND stLast.stop_sequence = tg.maxS
JOIN stops stFirstStop ON stFirst.stop_id = stFirstStop.stop_id
JOIN stops stLastStop ON stLast.stop_id = stLastStop.stop_id
SET t.origin = stFirstStop.stop_name,
    t.destination = stLastStop.stop_name,
    t.starts = stFirst.arrival_time,
    t.ends = stLast.arrival_time

注意:将trip_id更改为INT将为您提供更好的性能

此外,trip表应该存储origin_id和destination_id,稍后可以将其连接到停止表以查找名称,而不是将名称存储在所有行中