MS Access查询执行时间过长

时间:2009-09-22 04:13:38

标签: sql ms-access

我有Access 2003 with SQL后端。

此查询需要10分钟才能执行,如果我取出Exists部分需要10秒钟。

我不能把它作为直通查询放在SQL中,因为我需要在Access子报告中使用它。

任何想法如何改善执行时间??

SELECT DailyLeaveLedger.dldEmployeeID, 
       Sum(IIf([tolAnnualLeaveType]<>0,1,0)) AS ALDays, 
       Sum(IIf([tolPersonalLeaveType]<>0,1,0)) AS PLDays, 
       Sum(IIf([tolPublicHolidayType]<>0,1,0)) AS PHDays, 
       DailyLeaveLedger.dldPHID

FROM (DailyLeaveLedger 
      INNER JOIN Employees ON DailyLeaveLedger.dldEmployeeID = Employees.EmployeeID)   
      INNER JOIN TypeOfLesterLeave ON DailyLeaveLedger.dldLeaveType = TypeOfLesterLeave.tolID

WHERE (((DailyLeaveLedger.dldAuthDecline)=1) AND 
       ((DailyLeaveLedger.dldAuthorisedBy) Is Not Null) AND 
       ((DailyLeaveLedger.dldReleaseToPayroll)=True) AND 
       ((IIf([forms]![TransferTBRToPayrollForm]![chkOnlyPayLeave]=True,
                Exists (SELECT DISTINCT InvoiceHeader.InvDate 
                        FROM (InvoiceHeader 
                         INNER JOIN ReceiptDetail ON InvoiceHeader.InvNumber = ReceiptDetail.RDInvNumber) 
                         INNER JOIN [Work Codes] ON ReceiptDetail.RDWorkCodeID = [Work Codes].WorkCodeID 
                        WHERE ((ReceiptDetail.RDPayRun=0 Or 
                                ReceiptDetail.RDPayRun Is Null) AND 
                               (ReceiptDetail.RDRctToPayrollFlag=0) AND 
                               ([Work Codes].WorkCodePayrollAccount1<>0) AND 
                               (InvoiceHeader.EmployeeID = DailyLeaveLedger.dldEmployeeID) AND 
                              (DailyLeaveLedger.dldLeaveDate > DateAdd("ww", -InvoiceHeader.InvWeeksOfPay, InvoiceHeader.InvBeginDate)) AND 
                              (DailyLeaveLedger.dldLeaveDate <= InvoiceHeader.InvBeginDate)))
             ,True))=True))
GROUP BY DailyLeaveLedger.dldEmployeeID, DailyLeaveLedger.dldPHID
HAVING (((DailyLeaveLedger.dldPHID) Is Null));

3 个答案:

答案 0 :(得分:2)

让我们一次做一点。当我发现更多时,我会更新答案:

首先是简单的,删除select中的iif语句如下。

替换

SELECT DailyLeaveLedger.dldEmployeeID, 
       Sum(IIf([tolAnnualLeaveType]<>0,1,0)) AS ALDays, 
       Sum(IIf([tolPersonalLeaveType]<>0,1,0)) AS PLDays, 
       Sum(IIf([tolPublicHolidayType]<>0,1,0)) AS PHDays, 
       DailyLeaveLedger.dldPHID

SELECT DailyLeaveLedger.dldEmployeeID, 
       Sum([tolAnnualLeaveType] *-1) AS ALDays, 
       Sum([tolPersonalLeaveType] *-1) AS PLDays, 
       Sum([tolPublicHolidayType] *-1) AS PHDays, 
       DailyLeaveLedger.dldPHID

这将为您提供最低限度的改进。一旦我解开剩下的部分,我会给你一些更有影响力的。

其余部分是如此邪恶的混乱,我放弃试图解开它。但是,让我为您提供一些指导,说明您需要在一般意义上做什么而不是确切的代码。

基本上您需要做的是将此部分拉入主查询的连接而不是使用子查询。

(IIf([forms]![TransferTBRToPayrollForm]![chkOnlyPayLeave]=True,
                Exists (SELECT DISTINCT InvoiceHeader.InvDate 
                        FROM (InvoiceHeader 
                            INNER JOIN ReceiptDetail ON InvoiceHeader.InvNumber = ReceiptDetail.RDInvNumber) 
                            INNER JOIN [Work Codes] ON ReceiptDetail.RDWorkCodeID = [Work Codes].WorkCodeID 
                        WHERE ((ReceiptDetail.RDPayRun=0 Or ReceiptDetail.RDPayRun Is Null) AND 
                               (ReceiptDetail.RDRctToPayrollFlag=0) AND 
                               ([Work Codes].WorkCodePayrollAccount1<>0) AND 
                              (InvoiceHeader.EmployeeID = DailyLeaveLedger.dldEmployeeID) AND 
                              (DailyLeaveLedger.dldLeaveDate > DateAdd("ww", -InvoiceHeader.InvWeeksOfPay, InvoiceHeader.InvBeginDate)) AND 
                              (DailyLeaveLedger.dldLeaveDate <= InvoiceHeader.InvBeginDate)))
             ,True))=True))

这有意义吗?坦率地说,如果你不理解为什么抱怨将这个更改为传递,我有点担心你能够解决这个问题。它与从子报告中调用它无关,而更多与您使用VBA函数的事实有关。

答案 1 :(得分:0)

请提供格式化查询以便更好地理解.. 我已完成查询,发现原因可能是由于 EXIST 语句,其中您使用 InvoiceHeader.InvDate Invinyct

如果您仅使用Exist子句记录存在,那么我不知道您的具体情况,然后使用count(InvoiceHeader.InvDate)代替不同的InvoiceHeader.InvDate 我认为那时表现会增加..

答案 2 :(得分:0)

不确定Access正在做什么,但子报告将对主报告中的每条记录执行查询,因此我会在运行报告之前将此查询转储到表中。然后使用该表作为子报告记录源。

我在季度声明报告中使用了这个报告,该报告有几个子报告,它将时间从几个小时缩短到不到20分钟。