简体   繁体   中英

Microsoft Access 97/XP Left Join On Multiple Columns Fails - Vista/7 are fine

Im trying to do a left join on two tables to get all values that do not exist in table 2 or have a status of null:

Table 1 has ROID as long

Table 2 has ID long, Type long, and Status text.

This works fine on Vista and Win 7 (I get all the records that do not exist in V), but I get no records on XP,

  SELECT roid
  FROM
  wo AS w LEFT JOIN VFlag As V ON (w.roid = V.ID AND V.Type = 2)
  WHERE
  (V.Status is Null) 

When I remove the V.Type = 2, it works fine on XP/Vista/7, but I need to qualify on Type as well:

SELECT roid
  FROM
  wo AS w LEFT JOIN VFlag As V ON (w.roid = V.ID)
  WHERE
  (V.Status is Null)  

This is both in VB6 using ADO and VisData. Trying WHERE isnull(V.Status) did not make any difference. XP machines (two tested on) are SP3.

您是否尝试过将V.Type = 2放在WHERE子句中,而不是放在联接中?

I am a bit late to this - but I just came across what seems to be the same issue on Access 2003 Seems that the bug is fixed in latest JET. So could well explain the symptoms you saw and how fixed on Windows 7.

MS KB275058

mikecro

First, it is a known issue that Access's outer join is non-compliant with Standards, yields unexpected results and is less expressive as a result. The SQL Server team wanted to fix this 'bug' but was scuppered by the Windows Team ; it is higly unlikely that the engine has been fixed subsequently.

Second, nulls in SQL are a disaster generally. The SQL Standard fails to define three-valued logic. Access specifically also fails to three-valued logic and has numerous inconsistencies. It is best to avoid the null value and outer join is expressly designed to generate nulls.

Third, there is always more than way to express the same thing in SQL. The relational operator you require is semi difference aka antijoin . Your spec reads, "get all values that do not exist in table 2" so consider using NOT EXISTS eg

SELECT roid
  FROM wo AS w 
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM VFlag As V 
                    WHERE w.roid = V.ID 
                          AND V.Type = 2
                  );

I'm not sure whether the subquery should additionally test V.Type IS NULL because you've included implementation details ( LEFT OUTER JOIN ) in your spec and I can't see the trees for the wood :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM