2012-04-24 105 views
4

我在MS Access 2010数据库中有两个表:TBLIndividuals和TblIndividualsUpdates。他们有很多相同的数据,但主键可能与两个表中给定人的记录不同。所以我在名称和生日的两个表格之间进行连接,以查看哪些记录对应。我正在使用左连接,这样我也可以获得处于TblIndividualsUpdates但不在TBLIndividuals中的人员的行。通过这种方式,我知道需要将哪些记录添加到TBL个人中才能使其更新。为什么我的左连接Access的行数比左表的少?

SELECT TblIndividuals.PersonID AS OldID, 
TblIndividualsUpdates.PersonID AS UpdateID 
FROM TblIndividualsUpdates LEFT JOIN TblIndividuals 
ON ((TblIndividuals.FirstName = TblIndividualsUpdates.FirstName) 
and (TblIndividuals.LastName = TblIndividualsUpdates.LastName) 
AND (TblIndividuals.DateBorn = TblIndividualsUpdates.DateBorn 
    or (TblIndividuals.DateBorn is null 
     and (TblIndividuals.MidName is null and TblIndividualsUpdates.MidName is null 
      or TblIndividuals.MidName = TblIndividualsUpdates.MidName)))); 

TblIndividualsUpdates有4149行,但查询只返回4103行。 TblIndividualsUpdates中有大约50条新记录,但查询结果中只有4行OldID为空。

如果我将数据从Access导出到PostgreSQL并在那里运行相同的查询,我会得到所有4149行。

这是Access中的错误吗? Access的左连接语义和PostgreSQL之间有区别吗?我的数据库是否损坏(Compact和Repair不起作用)?

+0

可以运行'SELECT COUNT(*)FROM TblIndividualsUpdates;'告诉我们输出? – 2012-04-24 18:09:36

+0

@ypercube结果是4149 – andybalholm 2012-04-25 23:28:13

回答

3

这不应该发生。除非被插入的行/删除在此期间,

查询:

SELECT * 
FROM a LEFT JOIN b 
     ON whatever ; 

比应该不会返回更少的行:

SELECT * 
FROM a ; 

如果它发生,它是一个错误。你确定查询完全是这样的吗(你没有省略一些细节,比如WHERE条款)?你确定第一个返回4149行和第二个4103行?您可以通过将*更改为COUNT(*)来进行另一次检查。

+0

查看他的加入标准。他在'JOIN'条件下有'WHERE'标准。 – JNK 2012-04-24 17:56:32

+0

@JNK:我在查询中看到WHERE无处。 – 2012-04-24 17:57:46

+0

你说得对,我错了!删除了我的答案。 – JNK 2012-04-24 18:05:57

1

从两个表中删除包含JOIN字段(FirstName,LastName和DateBorn)的任何索引。然后查看是否使用此简化查询获得预期的 4,149行。

SELECT 
    i.PersonID AS OldID, 
    u.PersonID AS UpdateID 
FROM 
    TblIndividualsUpdates AS u 
    LEFT JOIN TblIndividuals AS i 
    ON 
     (
      (i.FirstName = u.FirstName) 
     AND (i.LastName = u.LastName) 
     AND (i.DateBorn = u.DateBorn) 
     ); 
+0

查询按照您给出的查询给出了4149行,在删除索引之前和之后。但是当我用'(i.DateBorn = u.DateBorn或i.DateBorn为空)替换'(i.DateBorn = u.DateBorn)''时,它只给出4136行。所以它似乎是触发错误的null检查。 – andybalholm 2012-04-26 18:11:18

+0

并非每个人都有数据库中的出生日期。如果旧表格和更新表格中的出生日期为空,则“i.DateBorn = u.DateBorn”将为空,并且记录不会连接。 '或i.DateBorn为空'捕捉这种可能性。 – andybalholm 2012-04-30 22:22:33

4
ON ( 

     TblIndividuals.FirstName = TblIndividualsUpdates.FirstName 

     and 

     TblIndividuals.LastName = TblIndividualsUpdates.LastName 

     AND (
       TblIndividuals.DateBorn = TblIndividualsUpdates.DateBorn  
       or 
       (
        TblIndividuals.DateBorn is null   
        and 
        (
        TblIndividuals.MidName is null 
        and TblIndividualsUpdates.MidName is null    
        or TblIndividuals.MidName = TblIndividualsUpdates.MidName 
        ) 
       ) 
      ) 
    ); 

我会做的是系统地删除除前两个所有的连接条件,直到找到记录脱落。然后你会知道你的问题在哪里。

+0

如果我删除条件,我得到错误匹配,所以我得到比原始表中更多的行,但有些行仍然被省略。真的,无论我的连接条件如何,我都不应该像左表那样得到更少的行,正如ypercube在他的答案中指出的那样。 – andybalholm 2012-04-26 00:03:52

0

无论什么价值,因为这似乎是一个欺骗性的错误和任何额外的信息可以帮助解决它,我也有同样的问题。

该查询太大而无法在此处发布,因此我现在没有时间将其降至合适的范围,但我可以报告发现的内容。在下面,所有连接都是左连接。

我正在逐渐完善和改变我的查询。它有一个派生表(D)。整个事情被编成派生表(T),然后加入到最后一个表(L)中。无论如何,在它的发展过程中,在T中没有起源于D的领域参与到L的连接中。然后问题发生了,神秘的行总数变得小于主表,这是不可能的。只要我再次让一个来自D的字段参与(通过T)到L中,该数字再次增加到正常。

这是因为如果参加条件d被移到WHERE子句中时,它没有字段在加盟L.正在参加(通过T),但我真的不知道解释是什么。