Access - Left Join返回#Error而不是Null

时间:2013-06-21 10:03:29

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

我已经问了一个类似的问题,但我现在已经简化了表/查询,足以建立一个带有(希望)描述性命名的示例数据库:

https://docs.google.com/file/d/0B2PZcGkhNyd4THpWa01fTjVvSWM/edit?usp=sharing

有一个查询,ChainsCasesPerMonthPerStorePreviousMonthRange,它工作正常。它从两个表和QueryDatesPrevious查询中获取数据,以将上一个句点的数据返回到QueryDates表中指定的数据。到目前为止,一切似乎还可以。

但是当我运行查询LeftJoinReturnsError时,Chains表中的三个额外链返回#Error而不是返回预期的Null。

如果我将QueryDatesPrevious从查询更改为表,一切正常,所以这似乎是问题所在,但我似乎无法解决它,即使使用Iif(IsNull,Null,0)条件。

额外的50个代表指向解决它的人,只要我能解决如何将它们转移过来。 :)

(上一个问题,如果你有兴趣:Access 2007 - Left Join to a query returns #Error instead of Null

- 编辑更新 -

输出看起来像这样,虽然我不记得我在测试数据库中输入的确切数据:

Chain                 CasesPerMonthPerStore
AgriStore             2.33
Agricultural Export   
2B Pencils            3.6
Bob's Markets         

所以基本上,Chain表中任何不在其他表中的链都应该返回Null作为左连接的一部分。

3 个答案:

答案 0 :(得分:1)

关于bug的好帖子。我没有看到,但很明显,这正是发生的事情。由于Access不支持横向连接或SQL Server的APPLY子句,因此我可以看到处理它的唯一方法是将表达式提升到顶级查询中的select子句。以下为您提供所需的输出:

SELECT Chains.Chain, (SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.CasesShipped/(DateDiff("m",ChainsCasesPerMonthPerStorePreviousMonthRange.StartDatePrevious,ChainsCasesPerMonthPerStorePreviousMonthRange.EndDatePrevious)+1)/ChainsCasesPerMonthPerStorePreviousMonthRange.NumberOfStores AS Expr1 from ChainsCasesPerMonthPerStorePreviousMonthRange WHERE ChainsCasesPerMonthPerStorePreviousMonthRange.Chain = Chains.Chain) as Expr2
FROM Chains;

这很难看,但它确实有效。当然,在SQL Server或其他数据库中,您不需要横向连接,因为进程外部正确连接表达式。

答案 1 :(得分:1)

这也很难看,但似乎有效:

运行以下查询以创建名为[tblChainsCasesPerMonthPerStorePreviousMonthRange]的表:

SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.* 
INTO tblChainsCasesPerMonthPerStorePreviousMonthRange
FROM ChainsCasesPerMonthPerStorePreviousMonthRange;

创建一个名为[updChainsCasesPerMonthPerStorePreviousMonthRange]的查询作为Update查询,将[ChainsCasesPerMonthPerStorePreviousMonthRange]的结果保存到[tblChainsCasesPerMonthPerStorePreviousMonthRange]中:

INSERT INTO tblChainsCasesPerMonthPerStorePreviousMonthRange
SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.*
FROM ChainsCasesPerMonthPerStorePreviousMonthRange;

将以下功能粘贴到标准VBA模块

Public Function RemakeTable() As Variant
Dim qdf As DAO.QueryDef
Debug.Print "Executing RemakeTable()..."
CurrentDb.Execute "DELETE FROM tblChainsCasesPerMonthPerStorePreviousMonthRange", dbFailOnError
Set qdf = CurrentDb.QueryDefs("updChainsCasesPerMonthPerStorePreviousMonthRange")
qdf.Execute
Set qdf = Nothing
RemakeTable = Null
End Function

将[LeftJoinReturnsError]查询更新为

SELECT 
    Chains.Chain, 
    tblChainsCasesPerMonthPerStorePreviousMonthRange.CasesPerMonthPerStore,
    RemakeTable() AS Junk
FROM 
    Chains 
    LEFT JOIN 
    tblChainsCasesPerMonthPerStorePreviousMonthRange 
        ON Chains.Chain=tblChainsCasesPerMonthPerStorePreviousMonthRange.Chain;

最终查询有一个名为[Junk]的额外列,但至少我们得到了所需的结果。

注意:我将Debug.Print放在VBA函数中以验证它只被调用一次,而不是查询中的每一行。

答案 2 :(得分:1)

好的,所以我设置了另一个查询,它只返回应该为CasesPerMonthPerStore返回Null值的链,但实际上在我的测试数据库中返回#Error:

SELECT Chains.Chain
FROM Chains LEFT JOIN ChainsNumStoresPreviousMonthRange ON Chains.Chain = ChainsNumStoresPreviousMonthRange.Chain
WHERE ChainsNumStoresPreviousMonthRange.NumberOfStores Is Null;

因此,在上面问题的书面示例中,此查询将返回:

Chain
Agricultural Export
Bob's Markets

然后我将这些链和Null字段UNION连接到返回所有为CasesPerMonthPerStore返回值的链的查询:

SELECT *
FROM (SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.Chain, ChainsCasesPerMonthPerStorePreviousMonthRange.CasesPerMonthPerStore
FROM ChainsCasesPerMonthPerStorePreviousMonthRange
UNION ALL
SELECT ChainsNotInPreviousPeriod.Chain, NULL
FROM ChainsNotInPreviousPeriod)  AS UnionQuery
ORDER BY Chain;

所以秘密似乎是将计算字段与左连接分开。这是我第一次遇到这个错误,我不知道这种方法是否适用于所有情况,但它对我有用。 :)

感谢您的时间Brian& GORD,