Projetando Esquema Simples para Desagregação da Previsão de Demanda

9

Estou executando uma tarefa simples de design de banco de dados como um exercício de treinamento em que preciso criar um design de esquema básico para o seguinte caso:

Eu tenho uma hierarquia pai-filho de produtos (exemplo: Matéria-prima> Trabalho em andamento> Produto final).

  • Os pedidos são feitos em cada nível.
  • O número de pedidos deve ser visualizado em baldes semanais pelos próximos 6 meses.
  • A previsão da demanda pode ser feita para cada nível do produto.
  • A previsão de demanda para qualquer semana nos próximos 6 meses pode ser feita hoje.
  • A previsão da demanda é feita para os intervalos semanais, para os próximos 6 meses.

A Previsão da demanda geralmente é feita no nível mais alto da hierarquia (nível de matéria-prima ou material em andamento). É necessário desagregar-se para um nível mais baixo (produto final).

Existem duas maneiras pelas quais a previsão de demanda pode ser desagregada de um nível mais alto para um nível mais baixo:

  1. O usuário especifica a distribuição percentual do produto final. Digamos, há uma previsão de 1000 para o trabalho em andamento. E o usuário diz que quero 40% para o produto final 1 e 60% para o produto final 2 no intervalo 10. Depois, para a 10ª semana (domingo a sábado), a partir de agora para o produto final 1 seria 400 e, para o produto final 2 seria 600.
  2. O usuário diz que apenas desagrega de acordo com os pedidos feitos nos produtos finais no balde 5 e os pedidos no balde 5 para o produto final 1 e 2 são 200 e 800 respectivamente, então o valor previsto para EP1 seria ((200/1000) * 100)% e para o EP2 seria ((800/1000) * 100)% da previsão para 'Trabalho em andamento'.

A previsão deve ser visualizada em intervalos semanais para os próximos 6 meses e o formato ideal deve ser:

product name | bucket number | week start date | week end date | forecast value | created_on

A tabela PRODUCT_HIERARCHY pode ficar assim:

id  |   name                |   parent_id
__________________________________________
1   |   raw material        |   (null)
2   |   work in progress    |   1
3   |   end product 1       |   2
4   |   end product 2       |   2

A tabela ORDERS pode ficar assim:

id | prod_id | order_date | delivery_date | delivered_date

Onde,

prod_idé uma chave estrangeira que faz referência idà tabela PRODUCT_HIERARCHY,

Como armazenar previsão? Qual seria um bom esquema básico para esse requisito?


Minha ideia para selecionar pedidos para 26 baldes semanais é:

SELECT
    COUNT(*) TOTAL_ORDERS,
    WIDTH_BUCKET(
        delivery_date,
        SYSDATE,
        ADD_MONTHS(sysdate, 6), 
        TO_NUMBER( TO_CHAR(SYSDATE,'DD-MON-YYYY') - TO_CHAR(ADD_MONTHS(sysdate, 6),'DD-MON-YYYY') ) / 7
    ) BUCKET_NO
FROM
    orders_table
WHERE
    delivery_date BETWEEN SYSDATE AND ADD_MONTHS(sysdate, 6);

Mas isso dará baldes semanais a partir de hoje, independentemente do dia. Como posso convertê-los para semanas de domingo a sábado no Oracle?

Por favor, ajude a projetar essa estrutura de banco de dados.

(usará o Oracle 11g)

Abhinav Sood
fonte
11
Parece que você está construindo um data warehouse. ordem seria a tabela de fatos. produto e data as tabelas de dimensão. Você pode usar uma tabela de fatos acumulativos, enquanto observa um processo que possui várias etapas.
Neil McGuigan

Respostas:

1

Ok, então aqui está o modelo de dados que eu criei.

PRODUCT - para armazenar informações do produto e manter a hierarquia pai-filho

id  NUMBER  "Primary Key Not Null"                  
level_code  VARCHAR2    Not Null                    
name    VARCHAR2    Not Null                    
description VARCHAR2                        
parent_id   NUMBER  Foreign Key references PRODUCT(id)                  

PEDIDOS - para armazenar pedidos de produtos

id  NUMBER  "Primary Key Not Null"                  
prod_id     NUMBER  "Foreign Key references PRODUCT(id) Not Null"                   
order_type  VARCHAR2    "Not Null Default 'Default'"
order_qty   NUMBER  Not Null
order_date  NUMBER  Foreign Key references DATE_INFO(date_key)
delivery_date   NUMBER  "Foreign Key references DATE_INFO(date_key)
Check delivery_date >= order_date"

PREVISÃO - para armazenar o valor previsto dos produtos (armazenar valor para níveis mais altos, armazenar valor para níveis mais baixos após a desagregação de um pai)

id  NUMBER  "Primary Key Not Null"
product_id  NUMBER  "Foreign Key references PRODUCT(id) Not Null"
forecast_value  NUMBER  Not Null
week    NUMBER  "Foreign Key references DATE_INFO(date_key) Not Null"                   

DISAGGREGATION_RULES - para armazenar qual método foi usado para desagregar um valor de um nível mais alto para um nível mais baixo e quanto percentual foi distribuído para um nível mais baixo

id  NUMBER  "Primary Key Not Null"
parent_product_id   NUMBER  "Foreign Key id references PRODUCT(id) Not Null"
child_product_id    NUMBER  "Foreign Key id references PRODUCT(id) Not Null"
method  VARCHAR2    Not Null                    
from_week   NUMBER  "Foreign Key references DATE_INFO(date_key) Not Null"
to_week NUMBER  "Foreign Key references DATE_INFO(date_key) Not Null Check end_week >= start_week"
percent_distribution    NUMBER  Not Null                    

DATE_INFO - dimensão da data, possui informações sobre a data de início (tem que ser sábado) e a data de término correspondente à semana em que uma determinada data cai

date_key    NUMBER  "Primary Key
Not Null"                   
full_date   DATE    Not Null                    
week_begin_date DATE    Not Null                    
week_end_date   DATE    Not Null

Quanto ao número do balde. Estou calculando a data de início da semana (data de sábado, no meu caso) com a seguinte função

CREATE OR REPLACE FUNCTION get_week_start_date(v_bucket_num IN NUMBER)
  RETURN DATE
IS
  week_start_date DATE;
BEGIN
  SELECT (TRUNC(SYSDATE+2, 'IW')-2) + ((v_bucket_num-1) * 7)
  INTO week_start_date FROM dual;
  RETURN week_start_date;
END;
Abhinav Sood
fonte