Do not input private or sensitive data. View Qlik Privacy & Cookie Policy.
Skip to main content

Announcements
Qlik Open Lakehouse is Now Generally Available! Discover the key highlights and partner resources here.
cancel
Showing results for 
Search instead for 
Did you mean: 
markgraham123
Specialist
Specialist

Create combinations of a set

Hi Team,

I'm trying to create all possible combinations of a number set. Can someone please help?

markgraham123_0-1630425471422.png

 

Labels (1)
1 Solution

Accepted Solutions
stevejoyce
Specialist II
Specialist II

Well this does seem a bit convoluted to me but i think this should work.  i expanded what i said originally but wrapped in a loop and created dynamic variables to handle n number of items in a list.  please check this out.

input:
load * inline [
list
2,11
2,7,11
5,8,17
3,8,17
2,11
2
11
1,2,7,20
1,2,3,4,5,6
] (delimiter is '|')
;


max_list_items:
load
max(substringcount(list, ',')) as max_list_items
resident input;

/*

*/

//creates rows for each item in list
item_rows:
load
list
,subfield(list, ',') as items1
resident input;

let maxitems = peek('max_list_items', 0, 'max_list_items');

//initial syntax
set vcombination_calc = items1;
set vcombination_whereclause = 1=1;

Trace vcombination_whereclause $(vcombination_whereclause);

for i = 2 to ($(maxitems))


//after first syntax
let vcombination_calc = '$(vcombination_calc)' & ' & ' & chr(39) & ',' & chr(39) & '& items' & $(i) ;
let vprevious_item = $(i) - 1;
let vcombination_whereclause = '$(vcombination_whereclause)' & ' and ' & '( items' & $(vprevious_item) & ' < items' & $(i) & ' )';

Trace vcombination_calc $(vcombination_calc);
Trace vcombination_whereclause $(vcombination_whereclause);

//cartesian product for all values for each list
left join (item_rows)
load distinct
list
,items1 as items$(i)
resident item_rows
;

//when num 1 < num 2 keep its combination

output:
load distinct
list
,$(vcombination_calc) as combination
//,items & ',' & items2 & ',' & items3 as combination
resident item_rows

where $(vcombination_whereclause);


next i

 

//add lists that have only 1 value
concatenate(output)
load
list
,list as combination
,1 as list_combination_id
resident input
where substringcount(list, ',') = 0;

drop table item_rows;
drop table input;

exit script;

View solution in original post

5 Replies
markgraham123
Specialist
Specialist
Author

@sunny_talwar Can you please help? 🙂

stevejoyce
Specialist II
Specialist II

Try this.   This gets all your data calculated.  If you want to have a 1-n combination fields, i can update it to create an ID for each combination in a list and can do a generic load.  let me know how you expect to use this data, but this calculates all the combinations.

 

input:
load * inline [
list
2,7,11
5,8,17
3,8,17
2,11
2
11
] (delimiter is '|')
;


//creates rows for each item in list
item_rows:
load
list
,subfield(list, ',') as items
resident input;

//cartesian product for all values for each list
left join (item_rows)
load
list
,items as items2
resident item_rows;

//when num 1 < num 2 keep its combination
output:
load
list
,items & ',' & items2 as combination
resident item_rows
where items < items2;

//add lists that have only 1 value
concatenate(output)
load
list
,list as combination
resident input
where substringcount(list, ',') = 0;

drop table item_rows;
drop table input;

markgraham123
Specialist
Specialist
Author

Hi @stevejoyce , This works for the above data. But not if I have a list with 4 digits : 1,2,7,20

The above codes generates sets of 2's. I want to look at combinations dynamically.

For the example: 1,2,7,20 

markgraham123_0-1630435907792.png

 

 

stevejoyce
Specialist II
Specialist II

Well this does seem a bit convoluted to me but i think this should work.  i expanded what i said originally but wrapped in a loop and created dynamic variables to handle n number of items in a list.  please check this out.

input:
load * inline [
list
2,11
2,7,11
5,8,17
3,8,17
2,11
2
11
1,2,7,20
1,2,3,4,5,6
] (delimiter is '|')
;


max_list_items:
load
max(substringcount(list, ',')) as max_list_items
resident input;

/*

*/

//creates rows for each item in list
item_rows:
load
list
,subfield(list, ',') as items1
resident input;

let maxitems = peek('max_list_items', 0, 'max_list_items');

//initial syntax
set vcombination_calc = items1;
set vcombination_whereclause = 1=1;

Trace vcombination_whereclause $(vcombination_whereclause);

for i = 2 to ($(maxitems))


//after first syntax
let vcombination_calc = '$(vcombination_calc)' & ' & ' & chr(39) & ',' & chr(39) & '& items' & $(i) ;
let vprevious_item = $(i) - 1;
let vcombination_whereclause = '$(vcombination_whereclause)' & ' and ' & '( items' & $(vprevious_item) & ' < items' & $(i) & ' )';

Trace vcombination_calc $(vcombination_calc);
Trace vcombination_whereclause $(vcombination_whereclause);

//cartesian product for all values for each list
left join (item_rows)
load distinct
list
,items1 as items$(i)
resident item_rows
;

//when num 1 < num 2 keep its combination

output:
load distinct
list
,$(vcombination_calc) as combination
//,items & ',' & items2 & ',' & items3 as combination
resident item_rows

where $(vcombination_whereclause);


next i

 

//add lists that have only 1 value
concatenate(output)
load
list
,list as combination
,1 as list_combination_id
resident input
where substringcount(list, ',') = 0;

drop table item_rows;
drop table input;

exit script;

markgraham123
Specialist
Specialist
Author

Thank you @stevejoyce . You are awesome! Really appreciate your help!