Which pairs of airports could have a direct route? Which combinations of three products could form a bundle? Such questions need every subset of a list. POWERMULTISET returns all non-empty subsets of a nested table, its power set, and POWERMULTISET_BY_CARDINALITY returns only the subsets of a given size.
Code for This Guide
The main example is in the examples/misc-functions folder of the Oracle Database 26ai code repository on GitHub, with its output. The repository also has the NIMBUS sample schema in the setup/nimbus folder.
It comes from Oracle Database 26ai SQL and PL/SQL Book.
Syntax
Syntax:
powermultiset(nested_table) powermultiset_by_cardinality(nested_table, cardinality)
The result is a nested table of nested tables, so it needs a type for each level, and it is read with TABLE().
Setup:
create or replace type t_codes as table of varchar2(10); create or replace type t_code_sets as table of t_codes;
All Subsets and Subsets of One Size
The first query returns every non-empty subset of three airports; the second only the pairs.
Example:
select * from table(powermultiset(t_codes('LHR', 'SIN', 'SYD')));
select * from table(powermultiset_by_cardinality(t_codes('LHR', 'SIN', 'SYD'), 2));Output:
COLUMN_VALUE __________________ [LHR] [SIN] [LHR, SIN] [SYD] [LHR, SYD] [SIN, SYD] [LHR, SIN, SYD] 7 rows selected. COLUMN_VALUE _______________ [LHR, SIN] [LHR, SYD] [SIN, SYD]
Three elements give seven non-empty subsets, 2 to the power 3 minus the empty set. The three pairs are all the direct routes a network of three cities could have.
Count Subsets by Size
Each subset is itself a collection, so CARDINALITY measures it, and ordinary SQL groups the result.
Example:
-- how many subsets of each size four airports have
select cardinality(column_value) as subset_size, count(*) as subsets
from table(powermultiset(t_codes('DXB', 'LHR', 'SIN', 'SYD')))
group by cardinality(column_value)
order by subset_size;Output:
SUBSET_SIZE SUBSETS
______________ __________
1 4
2 6
3 4
4 1Four airports have 4 single subsets, 6 pairs, 4 triples, and 1 set of all four: 15 in total.
Things to Know
- The number of subsets doubles with each element: 20 elements have more than a million subsets. Keep the input small, or use POWERMULTISET_BY_CARDINALITY to limit the size.
- For pairs only, a self-join with a.code < b.code is a simpler alternative that needs no types.
- Drop the types afterward with drop type t_code_sets and drop type t_codes.
Related Guides
Conclusion
POWERMULTISET returns every non-empty subset of a nested table, and POWERMULTISET_BY_CARDINALITY the subsets of one size. Define a collection type and a table of it for the result, read it with TABLE(), and keep the input small, since the number of subsets doubles with each element.
See my articles more often when you search Google.
