Совокупный запрос в MS-Access, который вычисляет текущие и совокупные суммы по счету, исключительно медленный - PullRequest
0 голосов
/ 25 февраля 2020

У меня проблемы с запросом доступа. Хотя он работает, он исключительно медленный; и я боюсь, что могу упускать из виду более простое и элегантное решение в моей структуре запросов.

Для контекста я работаю в офисе дебиторской задолженности. У нас тысячи клиентов, и у каждого клиента может быть один или несколько аккаунтов. Каждый месяц транзакции публикуются на различных счетах, и я готовлю счета для клиентов. В моем конкретном случае первый счет клиента всегда равен 001, затем 002 и т. Д. Мы выставляем счет ежемесячно.

Чтобы описать упрощенный пример , в январе 2020 года клиент A может иметь следующие транзакции в таблице транзакций:

+-----------------------------+
|TransID|Account|Amount|InvNum|
+-----------------------------+
|1      |1      |$10.00|001   |
|2      |2      |$5.00 |001   |
|3      |3      |$2.00 |001   |
+-----------------------------+

Так В приведенном выше примере я хотел бы выставить счет 001 клиенту А на общую сумму 17,00 долл. США, с разбивкой по счету. Счет будет выглядеть примерно так:


     +-----------------------+
     |Account|Current|ToDate |
     |1      |$10.00 |$10.00 |
     |2      |$5.00  |$5.00  |
     |3      |$2.00  |$2.00  |
     +-----------------------+
              $17.00  $17.00

Теперь предположим, что в феврале 2020 года дополнительные транзакции будут опубликованы. Упрощенная версия таблицы транзакций будет выглядеть следующим образом:

+-----------------------------+
|TransID|Account|Amount|InvNum|
+-----------------------------+
|1      |1      |$10.00|001   |
|2      |2      |$5.00 |001   |
|3      |3      |$2.00 |001   |
|4      |1      |$3.00 |002   |
|5      |3      |$4.00 |002   |
+-----------------------------+

Счет № 002, выданный клиенту A, должен выглядеть примерно так:

     +-----------------------+
     |Account|Current|ToDate |
     |1      |$3.00  |$13.00 |
     |2      |$0.00  |$5.00  |
     |3      |$4.00  |$6.00  |
     +-----------------------+
              $7.00   $24.00

Запрос Столкновение с проблемами специально предназначено для захвата активности месяца по счетам и , чтобы рассчитать совокупную сумму для столбца «ToDate» в счете-фактуре. Проблема в том, что не каждый аккаунт будет иметь транзакции в течение определенного месяца. Обратите внимание, что аккаунт 2 не проводил транзакций в феврале. Таким образом, в счете 002 должна быть указана текущая сумма в размере 0,00 долл. США для учетной записи 2, но также необходимо знать совокупную сумму (5,00 долл. США + 0,00 долл. США = 5,00 долл. США) для учетной записи 2.

Сам проблемный запрос c выполнен несколько подзапросов:

  1. BillNumByAcccountQ : сводный запрос, который выбирает и группирует все счета по номеру счета.
  2. CurrentQ : также агрегированный запрос, который выбирает и суммирует все суммы транзакции (из таблицы транзакций), который присоединяется к BillNumByAccountQ слева. Соединение влево необходимо, чтобы обеспечить наличие строки для каждого номера счета. Поле «Текущее» в этом запросе задается выражением Sum (Nz (Amount, 0)) . Результирующий набор этого запроса содержит более 20 тыс. Строк.

Наконец, проблемный запрос c определяется следующим оператором SQL:

SELECT 
   Q1.Account
    ,Q1.InvNum
    ,Q1.CURRENT
    ,(
        SELECT SUM(CURRENT)
        FROM CurrentQ
        WHERE Q1.Account = Account
            AND Q1.InvNum >= InvNum
        ) AS ToDate
FROM CurrentQ AS Q1;

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

Извиняюсь за столь большое количество информации, и я ценю любые советы по упрощению этого.

1 Ответ

0 голосов
/ 25 февраля 2020

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

Скорее всего, выполняется агрегация одновременно. будет быстрее:

SELECT 
     Q1.Account
    ,Q1.InvNum
    ,Q1.CURRENT
    ,SUM(i.CURRENT) AS ToDate
FROM CurrentQ AS Q1
JOIN CurrentQ AS i
     ON  i.Account = Q1.Account
     AND i.InvNum >= Q1.InvNum
GROUP BY Q1.Account, Q1.InvNum, Q1.Current;

Кроме того, если вы можете редактировать базу данных, вы, вероятно, захотите добавить индексы для столбцов Account и InvNum.

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