2013-06-21 24 views
2

我問過類似的問題了,但現在我已經簡化夠放了一個示例數據庫(希望)描述性的命名錶/查詢:訪問 - 左聯接返回#錯誤,而不是空

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

有一個查詢,ChainsCasesPerMonthPerStorePreviousMonthRange,它工作正常。它從兩個表和QueryDatesPrevious查詢中獲取數據,以便將前一個句點的數據返回到QueryDates表中指定的數據。在這個階段一切似乎都沒問題。

但是,當我運行查詢LeftJoinReturnsError,鏈表中的三個額外的鏈返回#Error,而不是返回預期的空值。

如果我將QueryDatesPrevious從查詢更改爲表,一切正常,所以這似乎是問題所在,但我似乎無法解決它,即使使用Iif(IsNull,Null,0)條件。

只要我能解決如何將它們轉移的問題,額外的50個代表指向解決問題的人。 :)

(前一個問題,如果你有興趣:Access 2007 - Left Join to a query returns #Error instead of Null

- 編輯更新 -

輸出會是這個樣子,雖然我不記得我把確切的數據測試數據庫:

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

因此,基本上,在鏈表的任何鏈,是不是其他表中應返回NULL作爲左邊的部分加入。

+0

要傳輸的代表,設置關於這個問題的賞金。你應該有足夠的代表。我會看看你的文檔。 –

+0

我看着它,我知道問題是什麼。我現在遠離Windows機器,所以我無法再檢查一切。只要我回來,我會發佈一個詳細的答案。 –

+0

你大挑逗Brian。 :) 17小時內有資格獲得賞金,所以我會在星期天這樣做,之後你可以發佈你的答案。我很想知道你的想法是什麼,因爲我迄今浪費了一天半的時間!乾杯, – Wilskt

回答

1

好了,所以我成立了另一查詢,只是返回應該返回CasesPerMonthPerStore Null值鏈,但在我的測試數據庫中實際上返回#錯誤:

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

所以在我寫的例子此查詢上面的問題將返回:

Chain 
Agricultural Export 
Bob's Markets 

我那麼UNION這些鏈,用一個空場一起,到返回所有做CasesPerMonthPerStore返回值鏈的查詢:

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

所以祕密似乎是將計算的字段從左連接中分離出來。這是我第一次遇到這個錯誤,我不知道這種方法是否適用於所有情況,但對我而言。 :)

感謝您的時間布賴恩&戈德,

1

關於bug的好貼子。我沒有看到,但很明顯,這正是發生了什麼事情。由於Access不支持橫向連接或SQL Server的APPLY子句,我可以看到處理它的唯一方法是將表達式提升到頂級查詢中的select子句。以下給出你想要的輸出:

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; 

這是非常醜陋的,但它的工作原理。當然,在SQL Server或其他數據庫中,您不需要橫向連接,因爲流程外部正確地與表達式連接。

+0

你可能想檢查你的工作。當我嘗試運行您的查詢時,系統會提示您輸入一些「參數」值,因爲存在無法識別的列名:「ChainsCasesPerMonthPerStorePreviousMonthRange.CasesShipped」,「ChainsCasesPerMonthPerStorePreviousMonthRange.StartDatePrevious」,... –

+0

認爲某些表名稱是混合的但是這並不奇怪,看他們是多久。我得到了這個工作的一個版本,它爲測試數據返回了正確的結果,但是當我擴展到我的工作數據時,查詢速度非常慢。我認爲它爲每個鏈調用一次嵌套的SELECT語句?所以它對我的完整數據集不起作用,但不可行。但我有一個想法,涉及一個單獨的左連接來查找應該返回Null值的鏈,然後將它們聯合到返回值的鏈上。如果我可以得到它的工作將會發布。 – Wilskt

1

這是相當醜陋過,但似乎工作:

運行下面的查詢,以創建一個名爲[tblChainsCasesPerMonthPerStorePreviousMonthRange]表:

SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.* 
INTO tblChainsCasesPerMonthPerStorePreviousMonthRange 
FROM ChainsCasesPerMonthPerStorePreviousMonthRange; 

創建一個名爲[updChainsCasesPerMonthPerStorePreviousMonthRange]作爲更新查詢將[ChainsCasesPerMonthPerStorePreviousMonthRange]的結果保存到[tblChainsCasesPerMonthPerStorePreviousMonthRange]中的查詢:

INSERT INTO tblChainsCasesPerMonthPerStorePreviousMonthRange 
SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.* 
FROM ChainsCasesPerMonthPerStorePreviousMonthRange; 

下面的函數粘貼到一個標準的VBA模塊

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 

更新您的[LeftJoinReturnsError]查詢

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

最後的查詢有一個名爲[垃圾]一個額外的列,但至少我們得到的預期的結果。

注意:我把Debug.Print放入VBA函數來驗證它只被調用一次,而不是查詢中的每一行調用一次。

+0

我不打算試試這個,因爲我想盡可能簡化數據庫以便下一個管理員使用,但我可以看到它是如何工作的。我是否認爲當你調用最後的SELECT語句時,使用Remaketable()AS垃圾進行調用時,它會調用VBA函數,然後刪除並更新表的內容?如果是這樣,我不知道你可以從標準的SELECT查詢中調用VBA函數!這開闢了許多新的途徑...... – Wilskt

+0

@Wilskt是的,這正是它所做的。從Access內部執行的查詢可以包括用VBA編寫的用戶定義的函數。在發佈這個函數之前,我嘗試了幾種不同的使用VBA函數的方法,因爲依賴RemakeTable()函數的副作用的想法不太吸引人,但是它似乎起作用,**(2)**它仍然使用最終SELECT查詢的「正常」調用(不需要記住首先運行單獨的查詢),並且**(3)**有時在解決「你」必須做你必須做的事情......「。 –