将mySQL子查询更改为联接以提高效率

将mySQL子查询更改为联接以提高效率,mysql,subquery,Mysql,Subquery,为了提高效率,是否可以将下面的mySQL查询更改为使用联接而不是子查询,或者以其他方式提高效率?我有一张病人去急诊室的桌子。该表列出了到达和离开时间。我需要这个查询来返回患者到达时已经在急诊科就诊的患者总数 我的桌子看起来像这样: +------+------+---------------------+---------------------+ | id | name | arrival | departure | +------+------

为了提高效率,是否可以将下面的mySQL查询更改为使用联接而不是子查询,或者以其他方式提高效率?我有一张病人去急诊室的桌子。该表列出了到达和离开时间。我需要这个查询来返回患者到达时已经在急诊科就诊的患者总数

我的桌子看起来像这样:

+------+------+---------------------+---------------------+
| id   | name |       arrival       |      departure      |
+------+------+---------------------+---------------------+
|    1 | Joe  | 2010-01-01 00:00:00 | 2010-01-01 02:00:00 |
|    2 | John | 2010-01-01 00:05:00 | 2010-01-01 03:00:00 |
|    3 | Jane | 2010-01-01 01:00:00 | 2010-01-01 04:00:00 |
...
+------+--------+
| name | census |
+------+--------+
| Joe  |   0    |
| John |   1    |
| Jane |   2    |
...
结果如下:

+------+------+---------------------+---------------------+
| id   | name |       arrival       |      departure      |
+------+------+---------------------+---------------------+
|    1 | Joe  | 2010-01-01 00:00:00 | 2010-01-01 02:00:00 |
|    2 | John | 2010-01-01 00:05:00 | 2010-01-01 03:00:00 |
|    3 | Jane | 2010-01-01 01:00:00 | 2010-01-01 04:00:00 |
...
+------+--------+
| name | census |
+------+--------+
| Joe  |   0    |
| John |   1    |
| Jane |   2    |
...
下面的查询可以工作,但在180000行上相当慢,大约3.5秒。有没有办法通过某种连接或其他方法来提高此查询的效率

select name, arrival,
    (SELECT count(*)
FROM patient_arrivals as b
WHERE b.arrival <= a.arrival and b.departure >= a.departure) as census
FROM patient_arrivals as a
我不认为加入会有帮助。相反,您需要重新构造查询。以下是任何特定时间房间内的患者人数:

  select t, sum(num) as num, @total := @total + num as total
  from (select arrival as t, 1 as num
        from patient_arrivals
        union all
        select departure, -1
        from patient_arrivals
       ) t cross join
       (select @total := 0) vars
  group by t
  order by t
然后,您可以将其用作联接的子查询:

select pa.*, t.total as census
from patient_arrivals pa join
     (select t, sum(num) as num, @total := @total + num as total
      from (select arrival as t, 1 as num
            from patient_arrivals
            union all
            select departure, -1
            from patient_arrivals
           ) t cross join
           (select @total := 0) vars
      group by t
      order by t
     ) tnum
     on pa.arrival = tnum.t;
这将给出患者到达时的编号。对于重叠的总数:

select pa.*, max(t.total) as census
from patient_arrivals pa join
     (select t, sum(num) as num, @total := @total + num as total
      from (select arrival as t, 1 as num
            from patient_arrivals
            union all
            select departure, -1
            from patient_arrivals
           ) t cross join
           (select @total := 0) vars
      group by t
      order by t
     ) tnum
     on tnum.t between pa.arrival and pa.departure
group by pa.id