【问题标题】:Slow MS Access Sub Query慢速 MS Access 子查询
【发布时间】:2018-07-09 23:41:13
【问题描述】:

我在 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 结果。

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

【问题讨论】:

  • 这个问题可能更适合Code Review
  • 谢谢。我也只是把它贴在那里还是可以移动?

标签: sql ms-access subquery


【解决方案1】:

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

与@LeeMac 类似,只需将您的所有表加入一个聚合查询,以获取按employee_id 分组的最大event_time,该查询将运行一次所有行。 times 下面是连接到聚合查询、employeestime_notes 表的 baseFROM 表:

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 

【讨论】:

  • 好奇的 OP,@nemmy,您是否尝试过上述查询?有什么错误吗?
【解决方案2】:

不确定这样的方法是否适合您?

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;

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

【讨论】:

  • 你的SQL功夫比我的好。我看到您要执行的操作,但 Access 没有。它以相当无用的“不支持 JOIN 表达式”作为响应。
  • @nemmy,我在发布后不久更新了我的代码 - 你尝试过更新版本吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
相关资源
最近更新 更多