Access 2007 – Left Join a una query restituisce #Errore anziché Null

Simile a questa domanda, ma il loro problema con la query non è mai stato completamente risolto:

#Errore visualizzato in più istruzioni LEFT JOIN Accedere alla query quando il valore deve essere NULL

Ottengo #Error quando mi aspetto di vedere un Null quando faccio un join di sinistra dove non c’è un record corrispondente sul lato destro del join:

Chain CasesPerMonthPerStore MonthOfFirstOrder Naturally 2.3 5/1/2011 Tom's Market #Error Livingstons #Error EverClear 3.1 7/1/2012 Bob's Market 2.66 5/1/2012 Andy's Exports #Error Jamestowns 0.89 7/1/2012 

Funziona bene se copio i dati in una tabella e se ne va a unirsi a questa tabella, quindi presumo che ci sia qualcosa di sbagliato nella syntax della query:

 SELECT MonthRange.Chain, MonthRange.CasesShipped/IIf(MonthsSinceFirstOrder.Months>DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1, DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1, MonthsSinceFirstOrder.Months)/NumStores.NumberOfStores AS CasesPerMonthPerStore, MonthsSinceFirstOrder.MonthOfFirstOrder FROM QueryDates, ( MonthRange INNER JOIN NumStores ON MonthRange.Chain=NumStores.Chain ) INNER JOIN MonthsSinceFirstOrder ON MonthRange.Chain=MonthsSinceFirstOrder.Chain; 

Questo SQL restituisce i risultati corretti, è solo il suo comportamento quando si unisce a sinistra che restituisce #Errors.

nb la strana dichiarazione Iif nei controlli di mezzo per vedere se il numero di mesi dal primo ordine è maggiore del numero di mesi inclusi nell’intervallo di date specificato, quindi se l’intervallo di date ha 6 mesi e il primo ordine era 9 mesi prima la data di fine, utilizza 6; se il primo ordine era solo 4 mesi prima della data di fine, utilizza 4.

– MODIFICA AGGIORNAMENTO –

Esatto, ho preso gli elementi della query uno per uno, e questo è il più semplice che posso ottenere mentre ricreavo ancora l’errore di unione a sinistra:

 SELECT MonthRange.Chain, DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1 AS CasesPerMonthPerStore FROM QueryDates, MonthRange; 

Ed è così che mi resta unito:

 SELECT Chains.Chain, ErrorQuery.CasesPerMonthPerStore FROM Chains LEFT JOIN ErrorQuery ON Chains.Chain=ErrorQuery.Chain; 

Qualcosa in questo SQL sembra sbagliato?

Mentre la query dovrebbe restituire Null in base al tipo di join, come afferma Allen Browne nel suo articolo, Bug: espressioni di join esterne recuperate erroneamente ,

“Al contrario, si comporta come se [l’ottimizzatore di query JET] stia valutando l’espressione dopo che ha restituito i risultati dalla query di livello inferiore.”

Di conseguenza, è necessario selezionare il campo calcolato utilizzando un’espressione che verrà valutata su Null se il lato destro del join non corrisponde al lato sinistro.

Usando il tuo codice ridotto come un esempio:

 SELECT Month.Chain, DateDiff("m",QueryDates.StartDate,QueryDates.EndDate)+1 AS CasesPerMonthPerStore FROM QueryDates, MonthRange; SELECT Chains.Chain, IIf(IsNull(ErrorQuery.Chain),Null,ErrorQuery.CasesPerMonthPerStore) FROM Chains LEFT JOIN ErrorQuery ON Chains.Chain=ErrorQuery.Chain; 

Sembra che potrebbe avere a che fare con un bug noto in Access, per cui commette errori sui join esterni con i campi calcolati:

http://allenbrowne.com/BugOuterJoinExpression.html

e

http://allenbrowne.com/bug-10.html

Quindi andrò a vedere se riesco a rieseguire le subquery per mascherare i campi calcolati in qualche modo.

Adoro Access. 🙂