2009-09-22 2 views
0

У меня есть Access 2003 с SQL-сервером.MSAccess запрос слишком длинный для выполнения

Этот запрос занимает 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)); 
+2

Что заставляет вас думать, что сквозной запрос запрещает использовать его в подзаголовке? Не то чтобы это важно, так как это, вероятно, будет так же плохо, как прохождение. – JohnFx

+0

Я вижу, что вы сейчас говорите. В запросе есть встроенные элементы управления, которые препятствуют работе сквозного доступа. Однако у вас большие проблемы.Предложение Exists, вложенное в iif, означает, что оно выполняется в каждой строке. Вы собираетесь переработать это, чтобы избавиться от существующего и iif-блока. Если вы объясните, что он пытается сделать, я смогу помочь вам переработать его. – JohnFx

+0

Он пытается выбрать дни отпуска из таблицы, и существует только для того, чтобы выбрать оставить строки, в которых отпуск находится в диапазоне счета-фактуры. т.е. время, на которое распространяется счет, если это имеет смысл. – Malcolm

ответ

2

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

Сначала легкий, избавитесь от инструкций 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.

+0

Когда я создал его в качестве прохода, я, очевидно, не ссылался на функции доступа VBA и поля отчета. Я создал 2 хранимых процедуры один с существующей частью и один с отсутствующей частью. Затем в моем коде VBA был изменен sql прохода через запрос, чтобы вызвать сохраненный процесс, который я хотел использовать для моих параметров формы. Сохраненная процедура с частью EXISTS выполняется через несколько секунд. Когда я запускаю отчет, открывается диалоговое окно «Доступ». Sayin «Вы не можете использовать сквозной запрос или нефиксированный запрос столбца столбца в качестве источника записи в подчиненную форму или подчиненный отчет». – Malcolm

+0

Что касается вашего предложения о заявлениях IIF, я считаю, что мой подход более читабельен, и хотя ваш способ может сэкономить дочки секунды. Но спасибо за ответ. – Malcolm

+0

IIF - функция VBA. Я могу ошибаться на полях, я ошибочно полагал, что некоторые из этих скобок упоминаются в форме или отчете. Как я уже сказал, эта вещь немного запутана без предварительного знания вашей структуры БД. – JohnFx

0

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

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

0

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

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

Смежные вопросы