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

时间:2014-06-29 15:52:55

标签: mysql subquery

是否可以更改以下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    |
...

以下查询有效,但速度很慢(180,000行约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

1 个答案:

答案 0 :(得分:0)

我不认为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

然后,您可以将其用作连接的子查询:

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