慢速MS Access子查询

时间:2018-01-31 00:00:48

标签: sql ms-access subquery

我在Access中有三个表:

employees
----------------------------------
id (pk),name

times
----------------------
id (pk),employee_id,event_time

time_notes
----------------------
id (pk),time_id,note

我希望在一段时间之前使用event_time从时间表中获取每个员工记录的记录。这样做很简单:

    select employees.id, employees.name, 
(select top 1 times.id from times where times.employee_id=employees.id and times.event_time<=#2018-01-30 14:21:48# ORDER BY times.event_time DESC) as time_id 
from employees

但是,我还希望了解time_notes表中是否有匹配的记录:

select employees.id, employees.name, 
(select top 1 time_notes.id from time_notes where time_notes.time_id=(select top 1 times.id from times where times.employee_id=employees.id and times.event_time<=#2018-01-30 14:21:48# ORDER BY times.event_time DESC)) as time_note_present,
(select top 1 times.id from times where times.employee_id=employees.id and times.event_time<=#2018-01-30 14:21:48# ORDER BY times.event_time DESC) as last_time_id 
from employees

这确实有效,但它太快了。如果员工表中有100条记录,我们正在谈论10秒或更长时间。问题是Access特有的,因为我不能像在MySQL或SQL Server中那样使用其他子查询的last_time_id结果。

我正在寻找有关如何提高速度的提示。不同的查询,索引。东西。

2 个答案:

答案 0 :(得分:1)

不确定这样的事情对你有用吗?

SELECT 
    employees.id, 
    employees.name, 
    time_notes.id AS time_note_present,
    times.id AS last_time_id
FROM 
    (
        employees LEFT JOIN 
        (
            times INNER JOIN
            (
                SELECT times.employee_id AS lt_employee_id, max(times.event_time) AS lt_event_time
                FROM times
                WHERE times.event_time <= #2018-01-30 14:21:48#
                GROUP BY times.employee_id
            )  
            AS last_times 
            ON times.event_time = last_times.lt_event_time AND times.employee_id = last_times.lt_employee_id
        ) 
        ON employees.id = times.employee_id
    )
    LEFT JOIN time_notes ON times.id = time_notes.time_id;

(完全未经测试,可能包含拼写错误)

答案 1 :(得分:0)

基本上,您的查询正在运行多个相关子查询,甚至是WHERE子句中的嵌套子查询。相关查询为每一行分别计算一个值,对应于外部查询。

与@LeeMac类似,只需将所有表格加入到按 employee_id 分组的最大 event_time 的汇总查询中,该 employee_id 将运行一次所有行。 下面是加入汇总查询的基本FROM表,员工 time_notes 表:

select e.id, e.name, t.event_time, n.note
from ((times t
inner join 
   (select sub.employee_id, max(sub.event_time) as max_event_time
    from times sub
    where sub.event_time <= #2018-01-30 14:21:48#
    group by sub.employee_id
   ) as agg_qry
on t.employee_id = agg_qry.employee_id and t.event_time = agg_qry.max_event_time)

inner join employees e
on e.id = t.employee_id)

left join time_notes n
on n.time_id = t.id