MSAccess запрос занимает слишком много времени для выполнения - PullRequest
0 голосов
/ 22 сентября 2009

У меня Access 2003 с бэкэндом 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 ]

2 голосов
/ 22 сентября 2009

Давайте сделаем это понемногу. Я обновлю ответ, когда найду больше:

Сначала просто, избавьтесь от операторов iif в select следующим образом.

Заменить

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.

0 голосов
/ 22 сентября 2009

Не знаю, что делает Access под этим, но подотчеты будут выполнять ваш запрос для каждой записи в основном отчете, поэтому я бы взял этот запрос и выгрузил его в таблицу перед запуском отчета. Затем используйте таблицу для источника записей подотчета.

Я использовал это в ежеквартальном отчете с несколькими подотчетами, и это сократило время с нескольких часов до менее 20 минут.

0 голосов
/ 22 сентября 2009

Пожалуйста, дайте нам отформатированный запрос для лучшего понимания .. Я прошел запрос и обнаружил, что причина может быть связана с оператором EXIST , в котором вы используете Distinct предложение для InvoiceHeader.InvDate

Я не знаю вашего точного сценария, если вы используете предложение Exist только для существования записи, тогда используйте счетчик (InvoiceHeader.InvDate) вместо отдельного InvoiceHeader.InvDate. я думаю, тогда производительность увеличится ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...