Записи истории, недостающие записи, заполнение пробелов - PullRequest
1 голос
/ 02 декабря 2009

У меня есть таблица, которая содержит историю затрат по местоположению. Они обновляются ежемесячно. Например

Location1, $500, 01-JAN-2009
Location1, $650, 01-FEB-2009
Location1, $2000, 01-APR-2009

если я сделаю запрос на 1 марта, я хочу вернуть значение на 1 февраля, поскольку 1 марта не существует. Я написал запрос с использованием аналитики оракула, но это занимает слишком много времени (было бы хорошо для отчета, но мы используем его, чтобы позволить пользователю визуально просматривать данные через передний план и и переключать даты, запрашивая данные слишком долго, если в таблице примерно 1 миллион строк). Итак, следующая мысль, которая у меня была, - просто обновить таблицу с отсутствующими данными. В приведенном выше случае я просто добавил бы запись, идентичную 01-ФЕВ-2009, за исключением того, что установил дату 01-MAR-2009.

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

Немного больше информации:

CREATE TABLE MAXIMO.FCIHIST_BY_MONTH
(
  LOCATION     VARCHAR2(8 BYTE),
  PARKALPHA    VARCHAR2(4 BYTE),
  LO2          VARCHAR2(6 BYTE),
  FLO3         VARCHAR2(1 BYTE),
  REGION       VARCHAR2(4 BYTE),
  AVG_DEFCOST  NUMBER,
  AVG_CRV      NUMBER,
  FCIDATE      DATE
)

И затем запрос, который я использую (система передаст дату и паркальфа). Таблица содержит около 1 миллиона строк, и, опять же, хотя отчету требуется разумное количество времени, для интерактивного отображения требуется слишком много времени

select location, avg_defcost, avg_crv, fcimonth, fciyear,fcidate from
(select location, avg_defcost, avg_crv, fcimonth, fciyear, fcidate,
max(fcidate) over (partition by location) my_max_date 
from FCIHIST_BY_MONTH 
where fcidate <='01-DEC-2008'
and parkalpha='SAAN'
)
where fcidate=my_max_date;

Ответы [ 3 ]

0 голосов
/ 02 декабря 2009

Лучший способ сделать это - создать хранимую процедуру PL / SQL, которая работает в обратном направлении от настоящего и выполняет запросы, которые не могут вернуть данные. Каждый месяц, когда он не может вернуть данные, он вставляет строку для отсутствующих данных.

create or replace PROCEDURE fill_in_missing_data IS
  cursor have_data_on_date is
    select locaiton, trunc(date_filed) have_date
    from the_table
    group by location, trunc(date_field)
    order by desc 1
  ;  
  a_date date;
  day_offset number;
  n_days_to_insert number;
BEGIN
   a_date := trunc(sysdate);
   for r1 in fill_in_missing_data loop
     if r1.have_date < a_date then
       -- insert dates in a loop
       n_days_to_insert := a_date - r1.have_date; -- Might be off by 1, need to test.
       for day_offset in 1 .. n_days_to_insert loop
         -- insert missing day
         insert into the_table ( location, the_date, amount ) 
            values ( r1.location, a_date-day_offset, 0 );
       end loop;
     end if; 
     a_date := r1.have_date;
     -- this is a little tricky - I am going to test this and update it in a few minutes
   end loop;
END;
0 голосов
/ 02 декабря 2009

Какой ваш конкретный вариант использования лежит в основе этого запроса?

В каждой системе, над которой я работал, если предполагается, что должна быть запись для МАРТА, и нет записи для МАРТА, пользователи хотели бы знать этот факт. Помимо всего, что они могли бы хотеть исследовать, почему запись МАРТА отсутствует.

Теперь, если это в основном проблема с производительностью, вам следует настроить запрос. Или, если это проблема презентации - вы хотите сгенерировать матрицу из двенадцати строк, и это сложно, если по какой-то причине нет записи - тогда это другой вопрос с множеством возможных решений.

А если серьезно, я считаю плохой практикой для базы данных придумывать замены для отсутствующих записей.

1010 * редактировать *

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

0 голосов
/ 02 декабря 2009

Заполнение пропущенных данных (если вы будете осторожны) сделает запросы намного проще и быстрее. Я бы также добавил флаг в таблицу, чтобы указать, что в данных отсутствуют заполненные данные, так что если вам нужно удалить его (или создать представление без него), позже вы сможете.

Я заполнил недостающие данные, а также пустые данные, чтобы внешнее объединение не было необходимым, чтобы повысить производительность запросов несколько раз. Это не «чистый» и «идеальный», но я следую закону № 1 Лефлара, «всегда идти с тем, что работает».

Вы можете создать в Oracle задание, которое будет автоматически запускаться в непиковое время для заполнения отсутствующих данных. Взгляните на: Этот вопрос о стекопереработке о создании рабочих мест.

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