【问题标题】:ms access complicated query. querying last two entries by date for each ID. very slowms访问复杂的查询。按日期查询每个 ID 的最后两个条目。非常慢
【发布时间】:2009-10-12 20:27:03
【问题描述】:

我有两张桌子。小部件,其中包含有关每个小部件的信息(颜色、大小等);每个小部件都有一个唯一的 ID,WidgetID。
另一个表是测试,它包含有关在每个小部件上运行的多个测试的信息。因此,该表对于每个 WidgetID 都有多行。它包含我们可以调用的信息(WidgetID、Date、Param1、Param2 等);测试信息。
我编写了一个查询,为每个 WidgetID 按日期查找最近的两个测试。 SQL 如下所示:

选择 Widgets.WidgetID、Widgets.Color、Widgets.Size、T.Date、T.Param1、T.Param2、*
FROM 测试 AS T INNER JOIN 小部件 T.WidgetID=Widgets.WidgetID
WHERE (((从测试中选择 COUNT(*))
WHERE WidgetID = T.WidgetID AND Date > T.Date))

这很好用。但是,它给了我太多的小部件。我创建了一个过滤名为 WidgetFilter 的小部件的查询。它基本上只是根据我选择的内容来选择我想要的。我的想法是我将运行相同的查询,将上面代码中的“Widgets”替换为“WidgetFilter”。但是,当我这样做时,它需要永远。事实上,它只是冻结。我把它放了一个半小时,它就坐在那里,我不得不 alt ctl delete。我唯一的想法是它正在为每一行测试查询 WidgetFilter 查询(那是很多行)。我还尝试在原始查询中应用过滤条件。我得到相同的结果。

有没有更好的方法来做到这一点?一个查询可以完成所有操作,甚至可能看起来不像这样,或者我在想应该有一种方法可以运行一次 WidgetFilter 查询并让该数据看起来像一个表一样访问(不存在这样的事情临时表)。这样它就不会为测试中的每个项目运行 WidgetFilter。

编辑:
WidgetFilter 实际上相当复杂。我创建了这些 GUI 选择表,用户可以在其中看到两列。左侧的选项和他/她正在创建的列表在右侧,中间有一个添加按钮和一个删除按钮。然后他们调用执行 WidgetFilter 的报告,yadda yadda yadda。无论如何,当用户添加一个项目时,它会将该项目添加到一个表中。因此对于 Widget 类别 Color,会有一个名为 ColorList 的表。用户通过 gui 构建此列表。其中有三种 gui(颜色、大小、类型)。对于它们中的每一个,都有一个表格,然后有一个全局布尔值(例如,ColorFlag),它告诉使用哪个过滤器(颜色、大小或类型)。
因此,在 WidgetFilter 查询中,Color 下的条件框将具有以下内容:
在(从颜色列表中选择颜色)
并且有一个表达式列 Expr1: getColorFlag() 这是一个返回全局变量 ColorFlag 值的模块。在应用颜色表的同时也是如此。因此,总而言之,有三行标准。代码如下所示:

选择 Widgets.WidgetID、Widgets.Color、Widgets.Size、Widgets.Type
从小部件
WHERE (getColorFlag() = True AND (Widgets.Color) In(Select Color FROM ColorList))
OR (getSizeFlag() = True AND (Widgets.Size) In(Select Size FROM SizeList))
OR (getTypeFlag() = True AND (Widgets.Type) In(Select Type FROM TypeList))

【问题讨论】:

    标签: ms-access count performance inner-join


    【解决方案1】:

    你可能不知道的一件事。我相信如果您有一个为任何行返回 NULL 值的子选择,大多数版本的 Access(不知道 2007 年)都会陷入困境。因此,如果这些表格中的任何颜色、大小或类型为 NULL,就会导致您看到的症状。

    【讨论】:

    • 我检查过了...事实并非如此。没有空值。不过谢谢。
    【解决方案2】:

    好的。这就是我最终做的事情。我通过 VBA 代码创建了一个临时表,如下所示:

    函数 createWidgetFilterTemp()
    暗淡的 mySQL
    暗淡删除SQL
    deleteSQL = "DELETE * FROM TempWidgetFilter"
    mySQL = "从 WidgetFilter 选择 * INTO TempWidgetFilter" DoCmd.SetWarnings 错误
    DoCmd.RunSQL deleteSQL
    DoCmd.RunSQL mySQL
    DoCmd.SetWarnings True
    结束函数

    我在一个名为 WidgetCombo 的查询中加入了 TempWidgetFilter 和测试。这使我可以访问所有测试信息和仅针对我感兴趣的 WidgetID 的所有 Widget 信息。我尝试使用 Select Count(*) 语句执行相同的查询,但我遇到了与 Access 冻结相同的问题.所以,然后我通过 VBA 使用如下代码创建了另一个临时表:

    函数 createWidgetTemp()
    暗淡的 mySQL
    暗淡删除SQL
    deleteSQL = "DELETE * FROM TempWidgetCombo"
    mySQL = "从 WidgetCombo 中选择 * INTO TempWidgetCombo" DoCmd.SetWarnings 错误
    DoCmd.RunSQL deleteSQL
    DoCmd.RunSQL mySQL
    DoCmd.SetWarnings True
    结束函数

    每当我从表单中调用查询时,我都会运行这两个函数。这有效!实际上,它工作得相当快。我认为如果没有第一个临时表它会工作,但是将它作为一个临时表而不只是一个查询使我的应用程序的另一部分运行得更快,所以我离开了它。顺便说一句,我必须在删除行注释掉的情况下运行一次,这样它才能创建表。我想我可能已经能够手动创建表格,但是这样它以正确的方式获得了所有字段。感谢您的帮助,我希望这可以帮助将来寻求临时表帮助的其他人。

    【讨论】:

      【解决方案3】:

      简单,真的。

      SELECT TOP 2 Widgets.WidgetID, Widgets.Color, Widgets.Size, T.Date, T.Param1, T.Param2,*
      FROM Tests AS T INNER JOIN Widgets ON T.WidgetID=Widgets.WidgetID
      ORDER BY T.Date DESC
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-27
        • 1970-01-01
        相关资源
        最近更新 更多