Question

I've asked a similar question already, but I've now simplified the tables/queries enough to put up an example database with (hopefully) descriptive naming:

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

There is one query, ChainsCasesPerMonthPerStorePreviousMonthRange, which works fine. It takes data from two tables and the QueryDatesPrevious query, to return data for the previous period to the one specified in the QueryDates table. Everything seems okay up to this stage.

But when I run the query LeftJoinReturnsError, the three extra chains in the Chains table return #Error instead of returning the expected Null.

If I change QueryDatesPrevious from a query to a table everything works fine, so this seems to be where the problem lies, but I can't seem to solve it, even using an Iif(IsNull, Null, 0) condition.

An extra 50 rep points to the person who solves it, as long as I can work out how to transfer them across. :)

(previous question if you're interested: Access 2007 - Left Join to a query returns #Error instead of Null)

-- EDIT UPDATE --

Output would look something like this, although I don't remember the exact data I put in the test database:

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

So basically, any chain in the Chain table that isn't in the other tables should return Null as part of the left join.

Was it helpful?

Solution 3

Okay, so I set up another query that just returns the chains that should return a Null value for CasesPerMonthPerStore, but are actually returning #Error in my test database:

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

So in my written example in the question above this query would return:

Chain
Agricultural Export
Bob's Markets

I then UNION these chains, along with a Null field, to the query that returns all of the chains that do return a value for CasesPerMonthPerStore:

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

So the secret seems to be to separate the calculated field away from the left join. It's the first time I've come across this error, and I don't know whether this approach would work in every situation, but it worked for me. :)

Thanks for your time Brian & Gord,

OTHER TIPS

This is rather ugly too, but it seems to work:

Run the following query to create a table named [tblChainsCasesPerMonthPerStorePreviousMonthRange]:

SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.* 
INTO tblChainsCasesPerMonthPerStorePreviousMonthRange
FROM ChainsCasesPerMonthPerStorePreviousMonthRange;

Create a query named [updChainsCasesPerMonthPerStorePreviousMonthRange] as an Update query that saves the results of [ChainsCasesPerMonthPerStorePreviousMonthRange] into [tblChainsCasesPerMonthPerStorePreviousMonthRange]:

INSERT INTO tblChainsCasesPerMonthPerStorePreviousMonthRange
SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.*
FROM ChainsCasesPerMonthPerStorePreviousMonthRange;

Paste the following Function into a standard VBA Module

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

Update your [LeftJoinReturnsError] query to

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

The final query has an extra column named [Junk], but at least we get the desired result.

Note: I put the Debug.Print in the VBA Function to verify that it only gets called once, not once for each row in the query.

Great post on the bug. I hadn't seen that, but it's quite obvious that's exactly what's happening. The only way I can see to deal with it since Access doesn't support lateral joins or SQL Server's APPLY clause, is to elevate the expression to the select clause in the top level query. The following gives you the output you want:

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;

It's pretty ugly, but it works. Of course in SQL Server or another DB, you wouldn't need lateral joins because the process outer joins with expressions correctly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top