MS Access: Error from WHERE condition evaluated on query inside join

依然范特西╮ 提交于 2020-01-07 03:52:15

问题


When I paste the following query into SQL View in Access 2007:

SELECT ID_Entry, DateVal
FROM (SELECT [Query A].ID_Entry, DateVal
     FROM [Query A] INNER JOIN [Query B] 
     ON [Query A].ID_Entry = [Query B].ID_Entry
     )  AS QueryAJoinB
ORDER BY ID_Entry, DateVal;

it returns a large recordset whose smallest value of ID_Entry is 19. I need to select records from that recordset based on the value of the field DateVal. (ID_Entry is a table index. DateVal is calculated as CDate(CleanRegData(<arguments with data from the current record>)). The function CleanRegData() is defined in VBA.) When I put a WHERE condition on DateVal, as such:

SELECT ID_Entry, DateVal
FROM (SELECT [Query A].ID_Entry, DateVal
     FROM [Query A] INNER JOIN [Query B] 
     ON [Query A].ID_Entry = [Query B].ID_Entry
     )  AS QueryAJoinB
WHERE DateVal = Date()
ORDER BY ID_Entry, DateVal;

the query crashes with an error on CleanRegData(). Debugging indicates that the function is called with arguments from the record for ID_Entry = 1. The error is correct because that record does not contain the data needed by CleanRegData(). That is the reason for using the above query -- to select the records for which DateVal can be evaluated before trying to evaluate it.

The recordset returned by Query A has values of ID_Entry that start with 19, but the recordset of Query B has all values of ID_Entry, starting with 1. The join on those two queries is supposed to reduce the recordset to only those records returned by Query A -- which are the records for which DateVal can be evaluated.

But it appears that putting the WHERE condition on field DateVal causes it to be evaluated for records in Query B, where the definition of that field is not valid. How do I get the WHERE condition to be executed only on the recordset of the join, and not on the queries inside the join?

Here is a picture of the second query above running in Design View:

Clicking on "Debug" takes me to CleanRegData() with its argument values obtained from the record for ID_Entry = 1, which does not have the data needed by CleanRegData(), which is why the query crashed. But if I delete the condition on DateVal, the query returns a recordset in the which the lowest value of ID_Entry is 19. So my question is, how is Access finding the data from that record for ID_Entry = 1? That record should not be available in this query. Or what am I not understanding that is making this happen?


回答1:


First, I would like to thank “Damien_The_Unbeliever”, who guided me, via his comments on my question, to understanding the source of the problem. As usual, once you understand the problem, the solution is at hand. I don’t know why he posted his remarks as comments instead of as an answer. Had he posted them as an answer, I’d have accepted it, but since he didn't I’m posting my own answer here so people can know the solution to the problem. I see that he already has a reputation of over 100k, so presumably he’s not concerned about the answer points.

Summarizing Damien’s comments, the problem was that Access was incorrectly and amazingly mixing the query's WHERE predicate with the join condition in the ON clause of the subquery! This caused it to attempt to evaluate DateVal on records for which that field is not defined, and thereby crash the query.

Here are references on this problem, the first provided by Damien, the others found with some research once I knew what to look for:

  • Discussion of a similar problem on Microsoft Connect: SQL Server should not raise illogical errors
  • Outer join analog of this problem documented by Allen Browne: Bug: Outer join expressions retrieved wrongly
  • Microsoft documentation of a problem that might be related (I haven't checked to see if it's really the same problem): ACC2000: Outer Join with WHERE Clause Returns Unexpected Records
  • StackOverflow discussion of the outer join analog of the problem: Access 2007 - Left Join to a query returns #Error instead of Null

In the fourth reference, the answer by “CWeb” gave me the clue to how to develop a workaround. What I had to do was put the WHERE predicate inside an iif() that tests the join condition again, which prevents DateVal from being evaluated on the wrong records. It’s a bit clugey, as workarounds always are, but it works. When I do that, I no longer need the subquery QueryAJoinB, whose purpose was to get the join to happen before the WHERE is evaluated, which wasn’t happening (which was the problem). Here is the query that works now:

SELECT ID_Entry, DateVal
FROM [Query A] INNER JOIN [Query B] ON [Query A].ID_Entry = [Query B].ID_Entry
WHERE IIf([Query A].[ID_Entry] = [Query B].[ID_Entry], [DateVal] = Date(), False)
ORDER BY ID_Entry, DateVal;

Success is sweet! Thanks again, Damien.



来源:https://stackoverflow.com/questions/34856574/ms-access-error-from-where-condition-evaluated-on-query-inside-join

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!