2012-04-24 101 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),但我真的不知道解釋是什麼。