# Provide me with all main products (which are not present in the sub products) with their lowest

Copper Contributor

# Provide me with all main products (which are not present in the sub products) with their lowest

I hope you are doing well, please find the problem statement below along with the sample data and output.

I have data with a product, sub-product, level and multiplying factor. Each product has multiple sub products, these sub products again have further subproducts, forming a hierarchy of data. Level "Ground" defines the lowest level of data. Below is the sample data.
 Product Sub product Level Multiplying Factor A B Sub1 0.9 A C Ground 0.8 A D Ground 0.7 B F Ground 0.3 G H Sub1 0.87 H I Sub2 0.99 I J Ground 0.88 G B Sub1 0.89 B F Ground 0.3

I need an output which will provide me with all main products (which are not present in the sub products) with their lowest level sub-products and denoted by Level " Ground" and their multiplying factor multiplied with each level until reaching "Ground" level. Below is a sample output of data. How do I obtain this in Excel.

 Product Sub product Level Multiplying Factor A C Ground 0.8 A D Ground 0.7 A F Ground 0.9*0.3 G J Ground 0.87*0.99*0.88 G F Ground 0.89*0.3
11 Replies

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

Hi,

I think you can add a helper table with XLOOKUP formulas to do this:

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

@srivatsa224 Based on the sample data provided, another option that might work is to use the REDUCE / VSTACK method to iterate through the main product data, applying a recursive LAMBDA function to each record:

``````=LET(
arr, UNIQUE(A2:D10),
main, FILTER(arr, ISNA(XMATCH(CHOOSECOLS(arr, 1), UNIQUE(CHOOSECOLS(arr, 2))))),
data, DROP(main,, 1),
results, DROP(REDUCE("", SEQUENCE(ROWS(data)), LAMBDA(v,n,
VSTACK(v, NEXTLEVEL(arr, CHOOSEROWS(data, n))))), 1),
HSTACK(CHOOSECOLS(main, 1), results)
)``````

The recursive LAMBDA function, NEXTLEVEL, is defined in Name Manager as follows:

``````NEXTLEVEL:
=LAMBDA(array,record,
IF(INDEX(record, 2)="Ground", record,
NEXTLEVEL(array,
LET(
sub, INDEX(record, 1),
arr, FILTER(DROP(array,, 1), CHOOSECOLS(array, 1)=sub, HSTACK(sub, "Ground", 1)),
IF(ISNUMBER(arr), record*arr, arr)
)
)
)
)``````

Results

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

@srivatsa224 Further to my previous response, if the sample data provided is not a complete and accurate representation of your actual data, there are certain scenarios that can return errors. For example, if the sub product combo "B / F" does not always appear at the "Ground" level, or if "B" can also be combined with other sub products such as "B / K".

Another option would be to use the SCAN function to assign ID numbers to each product grouping; however, this method requires the data to be arranged so that each product series appear together and in order from Sub1, Sub2, etc. to Ground. For example, your sample data shows the first record "A / B / Sub1" is separated from its corresponding "B / F / Ground" record by two other records. "A / B / Sub1" would need to be followed by "B / F / Ground" with nothing else in between them. If this is always true for your actual data, then the following formula should work:

``````=LET(
data, A2:D16,
id, SCAN(0, SEQUENCE(ROWS(data)), LAMBDA(v,n, IFS(n=1, 1, INDEX(data, n-1, 3)="Ground", v+1, TRUE, v))),
DROP(REDUCE("", UNIQUE(id), LAMBDA(v,n, LET(
arr, FILTER(data, id=n),
VSTACK(v, HSTACK(TAKE(arr, 1, 1), CHOOSECOLS(TAKE(arr, -1), 2, 3), PRODUCT(CHOOSECOLS(arr, 4))))))), 1)
)``````

Results

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

Product Sub_product Level Multiplying_Factor

 A B Sub1 0.9 A C Ground 0.8 A D Ground 0.7 B F Ground 0.3 G H Sub1 0.87 H I Sub2 0.99 I J Ground 0.88 G B Sub1 0.89 B F Ground 0.3

Product Sub_product level Multiplying_Factor

 A C Ground 0.8 A D Ground 0.7 A F Ground 0.27 G F Ground 0.267 G J Ground 0.757944

SQL:

``````select * from Bom_Calc_Factor;
with recursive under_alice as (select Product top,level,Sub_product,Product,Multiplying_Factor,Multiplying_Factor path from Bom_Calc_Factor where Product in (select distinct Product from Bom_Calc_Factor where Level like 'Sub1') union
select top,x.level,x.Sub_product,x.Product,x.Multiplying_Factor,under_alice.path*x.Multiplying_Factor from Bom_Calc_Factor x join under_alice on x.Product=under_alice.Sub_product)
select top Product,Sub_product,Level,path Multiplying_Factor from under_alice where Level like 'GROUND';``````

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

Don't get me wrong but I've always been intrigued by you guys' love of =Let in office365. perhaps it is because I don't use Excel that often.

Today I finally find a good use case of Let function so I decided to write another version of recursive lambda:

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

The 'Ground' level can be implicitly determined within your data structure as the termination point of a recursive function.

Take into account the following columns for input: products, subs, and factors:

``````=LET(
rows_sequence, SEQUENCE(ROWS(products)),
ground_subs, MAP(rows_sequence, LAMBDA(i, ground_sub(i, products, subs))),
total_factors, MAP(rows_sequence, LAMBDA(i, total_factor(i, products, subs, factors))),
data, HSTACK(products, ground_subs, total_factors),
FILTER(data, NOT(ISNUMBER(XMATCH(products, subs)))))``````

Recursive function ground_sub, which identifies the 'original' subproduct of any given product:

``````=LAMBDA(i, products, subs, LET(
sub, INDEX(subs, i),
new_i, XMATCH(sub, products),
IF(ISNUMBER(new_i), ground_sub(new_i, products, subs), sub)))``````

Recursive function total_factor, designed to multiply all intermediary factors of any given product:

``````=LAMBDA(i, products, subproducts, factors, LET(
subproduct, INDEX(subproducts, i),
new_i, XMATCH(subproduct, products),
INDEX(factors, i) * IF(ISNUMBER(new_i), total_factor(new_i, products, subproducts, factors), 1)))``````

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

Thanks for the solution, I tried for the given data and it works fine, but the complete data is large and
the sub product combination is not always the same and might vary. Also the product series data is not arranged together. It's not working in this case. Would you happen to have any solution ?

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

@srivatsa224 Possibly, but you would need to be able to somehow identify which records go together. If the dataset doesn't contain an ID column (ie: Group_ID) that can be used to link the related records together, and the data is not in any kind of logical order, it would be pretty tough to make this happen.

Can it always be determined that when a "non-Ground" record appears, the next occurrence of that particular Sub-product, found in the Product column, is the related record? For example, when "A / B / Sub1" appears, does that mean the next "B / ? / Sub2" or "B / ? / Ground" record is always the related record?

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

Hi,

Instead of writing two recursive lambdas and use map to get results in one go, I think you can just write a recursive lambda with row Index as parameter, and put SEQUENCE inside the lambda.

Writing lambda with row Index as parameter is very similar to the classic recursive factorial function.

I checked, I think it works pretty well:

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

Thank you, @rachel.,

This is a better approach, and I've downloaded your worksheet. However, I'm unable to refresh the formula in cell B14. I've tried pressing ENTER and CTRL + SHIFT + ENTER within the range B14:D22. How did you apply the formula?

# Re: Provide me with all main products (which are not present in the sub products) with their lowest

Select B14:D22, press F2, then press CTRL + SHIFT + ENTER: