【问题标题】:Access 2007 - Left Join to a query returns #Error instead of NullAccess 2007 - 左连接查询返回 #Error 而不是 Null
【发布时间】:2013-06-18 13:39:31
【问题描述】:

与这个问题类似,但他们的查询问题从未完全解决:

#Error showing up in multiple LEFT JOIN statement Access query when value should be NULL

当我期望在执行左连接时看到 Null 时出现 #Error,而右连接的右侧没有相应的记录:

Chain               CasesPerMonthPerStore   MonthOfFirstOrder
Naturally           2.3                     5/1/2011
Tom's Market        #Error
Livingstons         #Error
EverClear           3.1                     7/1/2012
Bob's Market        2.66                    5/1/2012
Andy's Exports      #Error
Jamestowns          0.89                    7/1/2012

如果我将数据复制到表中并左连接到该表,它工作正常,所以我认为查询的语法有问题:

SELECT 
    MonthRange.Chain,
    MonthRange.CasesShipped/IIf(MonthsSinceFirstOrder.Months>DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1,
                                DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1,
                                MonthsSinceFirstOrder.Months)/NumStores.NumberOfStores AS CasesPerMonthPerStore,
    MonthsSinceFirstOrder.MonthOfFirstOrder
FROM 
    QueryDates, 
    (
        MonthRange 
        INNER JOIN 
        NumStores 
            ON MonthRange.Chain=NumStores.Chain
    ) 
    INNER JOIN 
    MonthsSinceFirstOrder 
        ON MonthRange.Chain=MonthsSinceFirstOrder.Chain;

此 SQL 返回正确的结果,它只是在左连接时返回 #Errors 时的行为。

nb 中间奇怪的 Iif 语句检查自第一个订单以来的月数是否大于指定日期范围内包含的月数 - 所以如果日期范围有 6 个月并且第一个订单是结束日期前 9 个月,使用 6;如果第一个订单距离结束日期只有 4 个月,则使用 4。

-- 编辑更新--

好的,我将查询的元素一个一个取出,这是我能得到的最简单的,同时仍然重新创建左连接错误:

SELECT 
    MonthRange.Chain, 
    DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1 AS CasesPerMonthPerStore
FROM 
    QueryDates, 
    MonthRange;

这就是我加入它的方式:

SELECT 
    Chains.Chain, 
    ErrorQuery.CasesPerMonthPerStore
FROM 
    Chains 
    LEFT JOIN 
    ErrorQuery 
        ON Chains.Chain=ErrorQuery.Chain;

此 SQL 中是否有任何错误?

【问题讨论】:

  • 我无法使用 [MonthRange]、[QueryDates] 和 [Chains] 都是表的最小情况重新创建问题。 那些中的任何一个在您的情况下是已保存的查询吗?
  • 是的,有几个级别的嵌套查询可以做到这一点。我会检查这些查询,看看是否有任何问题。过去我遇到过一个问题,我对某个字段进行分组,然后从 Select 语句中删除了该字段,但意外地将其留在了 group by 子句中。 Access 没有意识到这一点,它在大多数情况下运行良好,但在某些情况下会引发奇怪的结果。如果我找到它的底部,我会在这里发布答案,感谢您抽出时间检查上面的查询。

标签: ms-access ms-access-2007 left-join


【解决方案1】:

虽然查询应该根据连接类型返回 Null,正如 Allen Browne 在他的文章 Bug: Outer join expressions retrieved wrongly 中所述,

“相反,它的行为就像 [JET 查询优化器] 在从较低级别的查询返回结果后评估表达式。”

因此,如果连接的右侧与左侧不匹配,则必须使用将评估为 Null 的表达式来选择计算字段。

以您的精简代码为例:

SELECT 
Month.Chain,
DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1 AS CasesPerMonthPerStore
FROM
QueryDates,
MonthRange;

SELECT
Chains.Chain,
IIf(IsNull(ErrorQuery.Chain),Null,ErrorQuery.CasesPerMonthPerStore)
FROM
Chains
LEFT JOIN
ErrorQuery
ON Chains.Chain=ErrorQuery.Chain;

【讨论】:

    【解决方案2】:

    这看起来可能与 Access 中的一个已知错误有关,它在与计算字段的外部联接中出错:

    http://allenbrowne.com/BugOuterJoinExpression.html

    http://allenbrowne.com/bug-10.html

    所以去看看我是否可以重新调整子查询以某种方式伪装计算字段。

    访问。 :)

    【讨论】:

    • RE:“以某种方式伪装计算字段” - 在您的示例数据库中重新创建错误后,我也在考虑相同的思路。我的猜测是计算的列是静态的(总是返回相同的值),所以查询优化器“短路”了外连接,只为每一行返回了该值。无论如何,感谢您发布您的答案;以后可能会对其他人有所帮助。
    • 在我的测试示例中,如果我将计算字段切换为常数(例如 3 或“测试”),那么这个值确实会出现在每个链上,无论它们是否出现在右侧加入与否。对于计算字段,它返回错误。只有当它是对单个字段的直接引用时,它才能正常工作。如果我确实解决了它,我会在这里发布解决方法。
    • 将其缩小到生成日期的查询,如果您有兴趣,可以在这里跟进问题:) stackoverflow.com/questions/17195928/…
    【解决方案3】:

    这是旧的,但我找到了一个解决方法,希望对某人有所帮助。我在右侧查询中遇到了同样的问题,但我也有一个并行的右侧查询,它具有类似的数据源和在左连接中正常工作的派生。不同之处在于工作右侧和具有简单计算字段的基础查询之间存在一个 UNION 查询。因此,我在麻烦的右侧查询和最终查询之间放置了一个 UNION 查询,方法是创建一个具有相同字段的空表,并与该表和原始右侧查询创建一个联合。工作得很好。根据 Wilskt 和 Allen Browne 提供的信息,我认为 UNION 正在迫使 Jet 推迟评估。

    【讨论】:

      猜你喜欢
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2017-01-01
      • 1970-01-01
      相关资源
      最近更新 更多