Заміна тимчасових таблиць в firebird

В даному випадку проблема полягає в тому, що колонку DENGI необхідно розбити на дві колонки, до того ж підрахувати підсумкову суму. "Лобове" рішення виглядає так:

  1. Робиться запит по доходах: SELECT NAME, DENGI FROM CASH WHERE DENGI> = 0.
  2. Потім робиться запит по видатках: SELECT NAME, DENGI FROM CASH WHERE DENGI.
  3. Потім підраховується підсумкова сума доходів: SELECT SUM (DENGI) FROM CASH WHERE DENGI> = 0.
  4. І, нарешті, підсумкова сума витрат: SELECT SUM (DENGI) FROM CASH WHERE DENGI.
  5. Отримані результати декількох запитів об'єднуються в клієнтському додатку в таблицю.

Всього знадобилося п'ять запитів. Використання тимчасових таблиць тут є найбільш ефективним рішенням. Для FIREBIRD рішення буде таким:

Другий підхід полягає у використанні комбінації FOR SELECT і зберігання в змінних збереженої процедури попередніх значень полів таблиці.

Відповідна процедура буде виглядати наступним чином:

Як окремий випадок перших двох підходів, слід зазначити можливість використання вкладеного оператора FOR SELECT INTO DO:

При цьому якщо інтерпретувати FOR SELECT як своєрідну "тимчасову" таблицю, то таке вкладення надає можливість працювати з декількома "тимчасовими" таблицями. Наприклад, якщо ведеться в окремій таблиці докладний облік по іншому члену сім'ї в такій же по структурі таблиці, як і CASH. але з ім'ям CASH2:

то щоб підвести загальний підсумок по двом членам сім'ї у вигляді:

можна реалізувати наступну процедуру:

Третій підхід застосовується в тих випадках, коли неможливо за умовами завдання впорядкувати попередньо вибірку. Тоді організовується псевдо тимчасова таблиця з необхідними полями, в процедурі проводитися спочатку її наповнення, а потім робиться необхідна обробка записів в такій таблиці. Ось як виглядає рішення задачі, поставленої при розгляді другого підходу, при використанні псевдо тимчасових таблиць:

Результат виконання процедури:

Так як з будь-якої причини в таблиці TEMP можуть залишитися "безгоспні" старі записи, то необхідно її періодично чистити (тут потрібно використовувати поле TDATE), наприклад, наступним чином:

Видалення "безгоспних" записів старше 10 днів

Зрозуміло, що третій підхід найповільніший з усіх, так як прохід по таблиці CASH здійснюється два рази, до того ж робляться вставки і оновлення записів в псевдо тимчасової таблиці і тільки потім виводиться результат. Сюди ж додається завдання забезпечення регулярного чищення таблиці TEMP. Перший і другий варіант будуть виконуватися значно бистрее- практично зі швидкістю вибірки записів. Як показує досвід, індексування таблиці CASH по сортируемое полю NAME дозволить домогтися отримання перших результатів виконання запиту через кілька секунд навіть на таблицях з кількістю записів рівним приблизно 10 млн. Рядків. У той же час при третьому підході час отримання перших записів складе кілька секунд вже на таблицях з кількістю записів рівним приблизно 10 тис. Рядків. Наприклад, при виконанні процедур ITOG2 і ITOG4 на наведених вище тестових прикладах були отримані наступні результати (дані програми IBExpert):

Схожі статті