Dynamic Forecasting is functionality that gives consultants the ability to create statistical forecasts on any level in the data structure hirarchy. Historically, all forecasts in the Inventory module utilize sku level forecasting but the Allocation module uses the Dynamic Forecasting component to create forecasts on item category level to calculate the buy mix percentages to allocate by. For fashion businesses it might make sense to create forecasts on article level and distribute down to sizes using size profiles or for Wholesale customers, it might make sense to create their forecasts on customer level.
IF OBJECT_ID('[dbo].[item_group_histories_sale]', 'U') IS NOT NULL
DROP TABLE [dbo].[item_group_histories_sale]
CREATE TABLE [dbo].[item_group_histories_sale](
[id] [INT] NOT NULL,
[date] [DATE] NOT NULL,
[value] [DECIMAL](18, 4) NOT NULL
CONSTRAINT [PK_item_group_histories_sale] PRIMARY KEY CLUSTERED
(
[id] ASC,
[date] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Inserting data into the table:
INSERT INTO [dbo].[item_group_histories_sale]
SELECT i.item_group_id AS id
,[history_date] AS [date]
,SUM([value]) AS [value]
FROM [dbo].[histories_sale] hs
INNER JOIN [dbo].[items] i ON hs.item_id = i.id
GROUP BY item_group_id, [history_date]
IF OBJECT_ID('[dbo].[item_group_forecast_details]', 'U') IS NOT NULL
DROP TABLE [dbo].[item_group_forecast_details]
CREATE TABLE [dbo].[item_group_forecast_details](
[id] [INT] NOT NULL,
[confidence_factor] AS (ISNULL([confidence_factor_overwrite],[confidence_factor_default])),
[skip_forc_to_date] AS (ISNULL([skip_forc_to_date_overwrite],[skip_forc_to_date_default])),
[forecast_from_date] AS (ISNULL([forecast_from_date_overwrite],[forecast_from_date_default])),
[forecast_to_date] AS (ISNULL([forecast_to_date_overwrite],[forecast_to_date_default])),
[confidence_factor_default] [DECIMAL](18, 4) NULL,
[confidence_factor_overwrite] [DECIMAL](18, 4) NULL,
[skip_forc_to_date_default] [DATE] NULL,
[skip_forc_to_date_overwrite] [DATE] NULL,
[forecast_from_date_default] [DATE] NULL,
[forecast_from_date_overwrite] [DATE] NULL,
[forecast_to_date_default] [DATE] NULL,
[forecast_to_date_overwrite] [DATE] NULL,
[forc_type] [INT] NULL,
[forecast_event_header_id] [INT] NULL,
[forecast_index_header_id] [INT] NULL,
CONSTRAINT [PK_item_group_forecast_details] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
IF OBJECT_ID('[dbo].[item_group_forecasts]', 'U') IS NOT NULL
DROP TABLE[dbo].[item_group_forecasts]
CREATE TABLE [dbo].[item_group_forecasts](
[id] [INT] NOT NULL,
[valid] [BIT] NOT NULL,
[forc_type] [SMALLINT] NOT NULL,
[date_created] [DATETIME] NOT NULL,
[model_family] [INT] NULL,
[y_mean] [DECIMAL](28, 4) NULL,
[y_sdev] [DECIMAL](28, 4) NULL,
[sigma] [DECIMAL](28, 4) NULL,
[rms_err] [DECIMAL](28, 4) NULL,
[rsq] [DECIMAL](28, 4) NULL,
[adj_rsq] [DECIMAL](28, 4) NULL,
[complexity] [DECIMAL](28, 4) NULL,
[aic] [DECIMAL](28, 4) NULL,
[bic] [DECIMAL](28, 4) NULL,
[mape] [DECIMAL](28, 4) NULL,
[raw_err] [DECIMAL](28, 4) NULL,
[mad] [DECIMAL](28, 4) NULL,
[n] [INT] NULL,
[d_error_mean] [DECIMAL](28, 4) NULL,
[d_error_std_dev] [DECIMAL](28, 4) NULL,
[forc_state] [SMALLINT] NULL,
[safety_stock_next_7_days] [DECIMAL](28, 4) NULL,
[safety_stock_next_14_days] [DECIMAL](28, 4) NULL,
[safety_stock_next_30_days] [DECIMAL](28, 4) NULL,
[safety_stock_next_60_days] [DECIMAL](28, 4) NULL,
[seasonality] [SMALLINT] NULL,
[confidence_factor] [DECIMAL](28, 4) NULL,
[trend] [SMALLINT] NULL,
[model_description] varchar(200) NULL,
CONSTRAINT [PK_item_group_forecasts] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
IF OBJECT_ID('[dbo].[item_group_forecast_values]', 'U') IS NOT NULL
DROP TABLE [dbo].[item_group_forecast_values]
CREATE TABLE [dbo].[item_group_forecast_values](
[id] [INT] NOT NULL,
[date] [DATE] NOT NULL,
[value] [DECIMAL](18, 4) NOT NULL,
CONSTRAINT [PK_item_group_forecast_values] PRIMARY KEY CLUSTERED
(
[id] ASC,
[date] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
The forecast and the history need to exist as data series
MERGE INTO [dbo].[data_element_series] AS Target USING
(VALUES
(12000,'item_group_sale',2,1,NULL,'{"caption":"ITEM_GROUP_HISTORIES_SALE","description":"DE_i_ITEM_GROUP_HISTORIES_SALE","data_object": { "name":"item_group_histories_sale","data_element_ref_table_id":3,"id_column":"id","date_column":"date"}}'),
(12001,'item_group_forecast',2,1,NULL,'{"caption":"ITEM_GROUP_FORECAST","description":"DE_i_ITEM_GROUP_FORECAST","data_object": { "name":"item_group_forecast_values","data_element_ref_table_id":3,"id_column":"id","date_column":"date"}}')
)
AS Source ([id],[name],[group_id],[system_default_element],[client_config],[server_config])
ON Target.[id] = Source.[id]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([id],[name],[group_id],[system_default_element],[client_config],[server_config])
VALUES ([id],[name],[group_id],[system_default_element],[client_config],[server_config]) ;
We need to add a entry into the dynamic forecast table for our new forecast:
DELETE FROM [dbo].[data_element_dynamic_forecast] WHERE id = 12000
INSERT INTO [dbo].[data_element_dynamic_forecast]([id], [input_data_element_name], [output_data_element_name], [header_table_name], [details_table_name], [forecast_batches], [safety_stock_output_de_name], [forecast_outliers_output_de_name])
SELECT 12000,'item_group_histories_sale','item_group_forecast','item_group_forecasts','item_group_forecast_details',1,NULL,NULL
The forecast requires stg_run
and stg_element
to be able to run the forecast. The following tables have to include the dynamic forecast:
core.stg_run
core.stg_group
core.stg_run_group
core.stg_element
core.stg_group_element
An dynamic forecast example is part of the standard setup so you should see row for dynamic forecast in all of these tables. The only thing that might require adjustment is what is in the parameters
column in core.stg_element
table. It must contain the id
of the dynamic forecast in dbo.data_element_dynamic_forecast
(Based on example above for item group forecast the parameters
column should include: /D:12000)
If the dynamic forecast example is missing the following code can be used to create it:
-- inserting into core.stg_run
MERGE INTO [agr_stg].[core].[stg_run] AS Target USING
(VALUES
('dynamic_forecast','Dynamic Forecast: Running for all ids',0,0,1)
)
AS Source ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
VALUES ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health]);
-- inserting into core.stg_group
MERGE INTO [agr_stg].[core].[stg_group] AS Target USING
(VALUES
('dynamic_forecast','Dynamic Forecast: Running for all ids', NULL)
)
AS Source ([name], [description], [system_health_group_id])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [system_health_group_id])
VALUES ([name], [description], [system_health_group_id]);
-- inserting into core.stg_run_group
MERGE INTO [agr_stg].[core].[stg_run_group] AS Target USING
(VALUES
('dynamic_forecast', 'dynamic_forecast', 1, 1)
)
AS Source ([stg_run_name], [stg_group_name], [run_order], [active])
ON (Target.[stg_run_name] = Source.[stg_run_name] AND Target.[stg_group_name] = Source.[stg_group_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_run_name], [stg_group_name], [run_order], [active])
VALUES ([stg_run_name], [stg_group_name], [run_order], [active]);
-- inserting into core.stg_element
MERGE INTO [agr_stg].[core].[stg_element] AS Target USING
(VALUES
('dynamic_forecast_all_ids', 'post_run', '', 'FORECASTS', 3, '/D:12000', NULL, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
)
AS Source ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
VALUES ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed]);
-- inserting into core.stg_group_element
MERGE INTO [agr_stg].[core].[stg_group_element] AS Target USING
(VALUES
('dynamic_forecast', 'dynamic_forecast_all_ids', 1, 0, 1)
)
AS Source ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
ON (Target.[stg_group_name] = Source.[stg_group_name] AND Target.[stg_element_name] = Source.[stg_element_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
VALUES ([stg_group_name], [stg_element_name], [run_order], [force_run], [active]);
Finally a task must be scheduled through the scheduler in the system or by adding a line to the dbo.scheduled_tasks
and you run the forecast through the task in the system.
If you want to be able to run forecast for one id within the dynamic forecasting (in the example used above, for one item group id) you can set it up with the following code snippet below. The only thing that needs to be adjusted for each specific scenario is the parameters
column when inserting into core.stg_element
. In this specific case below where the parameters
has ’/D:12000 /DU:1’, a forecast run is being setup to run dynamic forecast for:
dbo.data_element_dynamic_forecast
After this has been setup, you only need to update the id in the parameters
column in core.stg_element
to run dynamic forecast for another id in the future.
-- inserting into core.stg_run
MERGE INTO [agr_stg].[core].[stg_run] AS Target USING
(VALUES
('dynamic_forecast_by_id','Dynamic Forecast: Running for one id',0,0,1)
)
AS Source ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
VALUES ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health]);
-- inserting into core.stg_group
MERGE INTO [agr_stg].[core].[stg_group] AS Target USING
(VALUES
('dynamic_forecast_by_id','Dynamic Forecast: Running for one id', NULL)
)
AS Source ([name], [description], [system_health_group_id])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [system_health_group_id])
VALUES ([name], [description], [system_health_group_id]);
-- inserting into core.stg_run_group
MERGE INTO [agr_stg].[core].[stg_run_group] AS Target USING
(VALUES
('dynamic_forecast_by_id', 'dynamic_forecast_by_id', 1, 1)
)
AS Source ([stg_run_name], [stg_group_name], [run_order], [active])
ON (Target.[stg_run_name] = Source.[stg_run_name] AND Target.[stg_group_name] = Source.[stg_group_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_run_name], [stg_group_name], [run_order], [active])
VALUES ([stg_run_name], [stg_group_name], [run_order], [active]);
-- inserting into core.stg_element
MERGE INTO [agr_stg].[core].[stg_element] AS Target USING
(VALUES
('dynamic_forecast_one_id', 'post_run', '', 'FORECASTS', 3, '/D:12000 /DU:1', NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
)
AS Source ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
VALUES ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed]);
-- inserting into core.stg_group_element
MERGE INTO [agr_stg].[core].[stg_group_element] AS Target USING
(VALUES
('dynamic_forecast_by_id', 'dynamic_forecast_one_id', 1, 0, 1)
)
AS Source ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
ON (Target.[stg_group_name] = Source.[stg_group_name] AND Target.[stg_element_name] = Source.[stg_element_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
VALUES ([stg_group_name], [stg_element_name], [run_order], [force_run], [active]);
Now a task can be setup through the scheduler in the system and the forecast can be run for specific id.
If the forecast batches column (forecast_batches
) in dbo.data_element_dynamic_forecast
is larger than 1 then you can run the dynamic forecast for a specific batch. It can be setup and done with the code snippet below where you only need to change the parameters
column in the core.stg_element
table based on what batch is being run. In the example given below the parameters show ’/D:12000 /DB:2’ which represents:
dbo.data_element_dynamic_forecast
First setting number of batches to 10 as shown in code snippet below
UPDATE [dbo].[data_element_dynamic_forecast]
SET forecast_batches = 10
WHERE id = 12000
Then creating new stg_element
, stg_run
etc. for forecast batch number 2.
-- inserting into core.stg_run
MERGE INTO [agr_stg].[core].[stg_run] AS Target USING
(VALUES
('dynamic_forecast_by_batch','Dynamic Forecast: Running for specific batch',0,0,1)
)
AS Source ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
VALUES ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health]);
-- inserting into core.stg_group
MERGE INTO [agr_stg].[core].[stg_group] AS Target USING
(VALUES
('dynamic_forecast_by_batch','Dynamic Forecast: Running for specific batch', NULL)
)
AS Source ([name], [description], [system_health_group_id])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [system_health_group_id])
VALUES ([name], [description], [system_health_group_id]);
-- inserting into core.stg_run_group
MERGE INTO [agr_stg].[core].[stg_run_group] AS Target USING
(VALUES
('dynamic_forecast_by_batch', 'dynamic_forecast_by_batch', 1, 1)
)
AS Source ([stg_run_name], [stg_group_name], [run_order], [active])
ON (Target.[stg_run_name] = Source.[stg_run_name] AND Target.[stg_group_name] = Source.[stg_group_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_run_name], [stg_group_name], [run_order], [active])
VALUES ([stg_run_name], [stg_group_name], [run_order], [active]);
-- inserting into core.stg_element
MERGE INTO [agr_stg].[core].[stg_element] AS Target USING
(VALUES
('dynamic_forecast_one_batch', 'post_run', '', 'FORECASTS', 3, '/D:12000 /DB:2', NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
)
AS Source ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
VALUES ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed]);
-- inserting into core.stg_group_element
MERGE INTO [agr_stg].[core].[stg_group_element] AS Target USING
(VALUES
('dynamic_forecast_by_batch', 'dynamic_forecast_one_batch', 1, 0, 1)
)
AS Source ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
ON (Target.[stg_group_name] = Source.[stg_group_name] AND Target.[stg_element_name] = Source.[stg_element_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
VALUES ([stg_group_name], [stg_element_name], [run_order], [force_run], [active]);
Now a task can be setup through the scheduler in the system and the forecast can be run for the specific batch.
If you want to run forecast for specific set of ids it can be set up almost the same as with the one id example given above. The only difference is the parameters
column in core.stg_element
. Now the set of ids are listed up with comma between them: /D:12000 /DS:1,2,3.
dbo.data_element_dynamic_forecast
-- inserting into core.stg_run
MERGE INTO [agr_stg].[core].[stg_run] AS Target USING
(VALUES
('dynamic_forecast_by_set_ids','Dynamic Forecast: Running for set of ids',0,0,1)
)
AS Source ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health])
VALUES ([name], [description], [force_run], [run_stg_groups_in_sequence], [include_in_system_health]);
-- inserting into core.stg_group
MERGE INTO [agr_stg].[core].[stg_group] AS Target USING
(VALUES
('dynamic_forecast_by_set_ids','Dynamic Forecast: Running for set of ids', NULL)
)
AS Source ([name], [description], [system_health_group_id])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [description], [system_health_group_id])
VALUES ([name], [description], [system_health_group_id]);
-- inserting into core.stg_run_group
MERGE INTO [agr_stg].[core].[stg_run_group] AS Target USING
(VALUES
('dynamic_forecast_by_set_ids', 'dynamic_forecast_by_set_ids', 1, 1)
)
AS Source ([stg_run_name], [stg_group_name], [run_order], [active])
ON (Target.[stg_run_name] = Source.[stg_run_name] AND Target.[stg_group_name] = Source.[stg_group_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_run_name], [stg_group_name], [run_order], [active])
VALUES ([stg_run_name], [stg_group_name], [run_order], [active]);
-- inserting into core.stg_element
MERGE INTO [agr_stg].[core].[stg_element] AS Target USING
(VALUES
('dynamic_forecast_set_ids', 'post_run', '', 'FORECASTS', 3, '/D:12000 /DS:1,2,3', NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
)
AS Source ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
ON (Target.[name] = Source.[name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed])
VALUES ([name], [type_name], [description], [object], [operation_mode], [parameters], [src_data_object], [break_on_error], [add_missing_columns_to_target], [data_merge_column_values], [data_merge_join_columns], [data_merge_compare_columns], [data_merge_update_columns], [data_merge_insert_columns], [data_merge_not_match_source_values], [data_merge_filter], [data_merge_source_only_filter], [data_merge_pre_sql], [data_merge_post_sql], [last_run_time], [last_run_time_successful], [last_run_event_id], [last_run_failed]);
-- inserting into core.stg_group_element
MERGE INTO [agr_stg].[core].[stg_group_element] AS Target USING
(VALUES
('dynamic_forecast_by_set_ids', 'dynamic_forecast_set_ids', 1, 0, 1)
)
AS Source ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
ON (Target.[stg_group_name] = Source.[stg_group_name] AND Target.[stg_element_name] = Source.[stg_element_name])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([stg_group_name], [stg_element_name], [run_order], [force_run], [active])
VALUES ([stg_group_name], [stg_element_name], [run_order], [force_run], [active]);
As before, a task can be setup through the scheduler in the system and the forecast can be run for this specific set of ids in the system.
IF OBJECT_ID('[dbo].[item_group_safety_stock]', 'U') IS NOT NULL
DROP TABLE [dbo].[item_group_safety_stock]
CREATE TABLE [dbo].[item_group_safety_stock](
[id] [INT] NOT NULL,
[days] [SMALLINT] NOT NULL,
[value] [DECIMAL](18, 4) NOT NULL,
CONSTRAINT [PK_item_group_safety_stock] PRIMARY KEY CLUSTERED
(
[id] ASC,
[days] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
UPDATE [dbo].[data_element_dynamic_forecast]
SET safety_stock_output_de_name = 'item_group_safety_stock'
WHERE id = 12000
IF OBJECT_ID('[dbo].[item_group_forecast_outliers]', 'U') IS NOT NULL
DROP TABLE [dbo].[item_group_forecast_outliers]
CREATE TABLE [dbo].[item_group_forecast_outliers](
[id] [INT] NOT NULL,
[iteration] [INT] NOT NULL,
[error_mean] [DECIMAL](28, 4) NOT NULL,
[error_std_dev] [DECIMAL](28, 4) NOT NULL,
[value] [DECIMAL](28, 4) NOT NULL,
[corrected] [DECIMAL](28, 4) NOT NULL,
[offset] [INT] NOT NULL,
CONSTRAINT [PK_item_group_safety_forecast_outliers] PRIMARY KEY CLUSTERED
(
[id] ASC,
[iteration] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
UPDATE [dbo].[data_element_dynamic_forecast]
SET forecast_outliers_output_de_name = 'item_group_forecast_outliers'
WHERE id = 12000
The outliers table is only written to if any outliers are found!