Хранение еженедельных и ежемесячных агрегатов в Oracle

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

Какая структура таблиц лучше всего для удержания продаж в течение периода?

  • Сохранить тип периода (M, W) с датами начала и окончания или только тип и дату начала?
  • Используйте поля даты и символ или закодируйте его в строку ('M201201' / 'W201248')
  • Нормализовать продажи и периоды в две таблицы или сохранить продажи и период в одной таблице?

Я буду выполнять два типа запросов: выбирать продажи за текущий недельный (xor ежемесячный) период / покупателя / статью, но не обновлять их, и выбирать для обновления еженедельные и ежемесячные периоды для покупателя / статьи.


person Kim Sullivan    schedule 21.01.2012    source источник


Ответы (2)


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

Сказать where @date_of_interest >= start_date and @date_of_interest <= end_date очень прямо и просто. Любая другая комбинация требует, чтобы вы выполняли арифметику даты либо в коде, прежде чем переходить к запросу, либо внутри самого запроса.

Сохранение кода типа (M, W), а также даты начала и окончания влечет за собой некоторую избыточность. Однако вы можете выбрать эту избыточность для облегчения извлечения данных. Это: where @date_of_interest >= start_date and @date_of_interest <= end_date and range_type='M' также очень прямолинейно и просто.

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

person Joel Brown    schedule 22.01.2012
comment
Спасибо, хороший момент по поводу арифметики даты - это тоже было моей первоначальной заботой. К сожалению, я не смогу избежать этого, потому что я должен указать правильную дату при создании записи - я не могу просто использовать TRUNC (@ date_of_interest, 'IW') из-за нашей структуры ORM. - person Kim Sullivan; 22.01.2012

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

Наверное что-то вроде этого образца

product_prices (
    prod_code,
    price,
    date_price_begin
);

sales (
    prod_code,
    customer_code,
    sale_date
);


<aggregate-week>
select trunc(sale_date,'w') as week,
    prod_code,
    customer_code,
    sum(price) keep (dense_rank first order by date_price_start) as price
from sales 
    natural join product_prices
where sale_date > date_from
group by trunc(sale_date,'iw'),
    prod_code,
    customer_code
/

<aggregate-month>
select trunc(sale_date,'m') as month,
    prod_code,
    customer_code,
    sum(price) keep (dense_rank first order by date_price_start) as price
from sales 
    natural join product_prices
where sale_date > date_from
group by trunc(sale_date,'m'),
    prod_code,
    customer_code
/
person Alessandro Rossi    schedule 22.01.2012
comment
Я не могу выполнить фактическую агрегацию sql, я попробовал это однажды (используя представление), и это было недостаточно быстро (мне нужно проверять агрегированные данные о продажах для каждой строки заказа). Кроме того, меня интересует фактическое количество штук, проданных в течение всего периода, а не цена, начатая с начала периода. Каковы преимущества использования двух таблиц вместо одной таблицы с индексом или даже одной таблицы с двумя разделами? - person Kim Sullivan; 24.01.2012
comment
Я не могу представить, как этот запрос может быть медленным !! Таблицы, которые они используют, не будут такими большими (менее 50 байтов для каждой строки), а таблицы агрегации могут быть построены постепенно (путем добавления новых строк в конце каждой недели / месяца). В любом случае я протестирую случай и обновлю свой пост с результатами. - person Alessandro Rossi; 25.01.2012
comment
Я думаю, вы неправильно поняли, мне не нужен еженедельный агрегат после окончания недели, мне он нужен в течение недели (как часть учета запасов). Это означает, что когда я обрабатываю продажу товара 123456 для клиента 100000 в среду 13:45, мне нужны общие продажи для товара с 00:00 понедельника до начала транзакции в среду. Если каждый раз, когда я хочу продать продукт покупателю, мне приходится выполнять «ВЫБРАТЬ .. ГРУППИРОВАТЬ ПО» для данных о продажах, база данных просто не сможет справиться с этим. Вот почему я должен делать инкрементное обновление агрегата после каждой продажи. - person Kim Sullivan; 27.01.2012