With any luck I can describe my requirement without confusing myself...
I have a multi-level dataset where users can flag which records to summarise into different totals.
Data Entry Rules:
- IF 'Base Unit' column (True/False) is checked (i.e. True) then 'Add for Option #' and 'Remove for Option #' must be NULL.
- IF 'Add for Option #' or 'Remove for Option #' is set then 'Base Unit' column must be FALSE.
- IF 'Add for Option #' is set then; the option list (letters A-Z, separated by semi-colons) cannot include a letter that is in the same structure at a different level (for example for Sequence No = 300, 'Add for Option #' could not include 'B' or 'D'. Same rule applies for the 'Remove for Option #' column.
- IF 'Add for Option #' or 'Remove for Option #' is set then the same row cannot contain the same option (i.e. letter), for example; for Sequence No = 300, 'Add for Option #' could not include 'B' or 'D'.
The 'Purch Cost/Curr' column is only populated for the lowest level for each structure - these values are already multiplied by the Qty.
I need a PLSQL function that will:
- Dependent on parameter (is_base_
/ option_
), find all rows where the 'Base Unit' column = is_base_
OR ('Add for Option #' column or 'Remove for Option #' column contain option_
). For example:
select sequence_no,
part_no,
component_part,
base_unit
add_for_option,
remove_for_option
from prod_conf_cost_struct
where (base_unit = is_base_ and base_unit = 'True'
or (add_for_option = option_ or remove_for_option = option_));
Loop through all rows returned by the query above and summarise PER CURRENCY the total of the 'Purch Cost/Curr' column, for each level in the structure. The main challenge I face is that once I have the total for a Level 2 row I cannot multiple that by the 'Qty' at that level before continuing up the structure.
- If calculating the total for an Option the 'Remove for Option #' value must be subtracted from the 'Add for Option #' value.
Here is my NEW attempt:
function calc_cost(
model_no_ number,
revision_ number,
sequence_no_ in number,
currency_ in varchar2
) return number is
qty_ number := 0;
cost_ number := 0;
begin
select nvl(new_qty, qty), purch_cost
into qty_, cost_
from prod_conf_cost_struct_clv
where model_no = model_no_
and revision = revision_
and sequence_no = sequence_no_
and (purch_curr = currency_ or purch_curr is null);
if cost_ is null then
select sum(calc_cost(model_no, revision, sequence_no, purch_curr)) into cost_
from prod_conf_cost_struct_clv
where model_no = model_no_
and revision = revision_
and (purch_curr = currency_ or purch_curr is null)
and part_no in (
select component_part
from prod_conf_cost_struct_clv
where model_no = model_no_
and revision = revision_
and sequence_no = sequence_no_);
end if;
return qty_ * cost_;
exception when no_data_found then
return 0;
end calc_cost;
In addition to the 'Sequence No' column there is 'Model No' and 'Revision'.
MODEL_NO - REVISION - SEQUENCE_NO
would make up the composite key.
select level, sys_connect_by_path(sequence_no, '->') path,
calc_cost(model_no, revision, sequence_no, 'GBP') total_gbp,
calc_cost(model_no, revision, sequence_no, 'EUR') total_eur,
calc_cost(model_no, revision, sequence_no, 'USD') total_usd
calc_cost(model_no, revision, sequence_no, '???') total_other
from prod_conf_cost_struct_clv
where model_no = 35
and revision = 2
connect by prior component_part = part_no
and prior model_no = 30
and prior revision = 2
start with sequence_no = 22500
order by sequence_no
I require the totals per currency summarised like this (when the Base/Option column is blank it will summarise for when BASE_UNIT = True
):