Technical Article

Generating combinations 'm elements from n-element set'

,

This procedure generates a dataset with combinations of elements_to_select taken from number_of_values element set. It prints also the prepared query.

/******************************************************************************
*
* Author Rafal Skotak
* Purpose This procedure generates a dataset with combinations of
* elements_to_select taken from number_of_values element set
* Date 2008-01-2
*
*******************************************************************************/

if exists(select * from sys.objects where object_id = object_id('dbo.proc_generate_combinations') and type = 'P')    
drop procedure dbo.proc_generate_combinations
go

create procedure dbo.proc_generate_combinations
@number_of_values integer,
@elements_to_select integer
as
begin
--------------------------------------------------------------
-- check parameters values

if @number_of_values is null
begin
raiserror('Number of values is null', 16, 1)
return
end

if @elements_to_select is null
begin
raiserror('Elements to select is null', 16, 1)
return
end

if @number_of_values < 1 or @number_of_values > 18
begin
raiserror('Invalid value of number_of_values', 16, 1)
return
end

if @elements_to_select > @number_of_values or @elements_to_select < 1
begin
raiserror('Invalid value of elements_to_select', 16, 1)
return
end

--------------------------------------------------------------------------------------
-- prepare parts of the query

declare @n_unions nvarchar(max)
declare @n_select_list nvarchar(max)
declare @n_glued_value nvarchar(max)
declare @n_glued_ascii_value nvarchar(max)
declare @n_joins nvarchar(max)
declare @n_counter nvarchar(16)

declare @values_counter int

set @values_counter = 0

set @n_unions = N''
set @n_select_list = N''
set @n_glued_value = N''
set @n_glued_ascii_value = N''
set @n_joins = N''

while @values_counter < @number_of_values
begin
set @n_counter = cast(@values_counter as nvarchar(16))
set @n_unions = @n_unions + N' select ' + @n_counter + N' as val union '

if @values_counter < @elements_to_select
begin
set @n_select_list = @n_select_list + char(13) + N' comb' + @n_counter + N'.val, '

set @n_glued_value = @n_glued_value + char(13) + N' cast(comb' + @n_counter + N'.val as varchar(64)) + '

set @n_glued_ascii_value = @n_glued_ascii_value + char(13) + N' char(comb' + @n_counter + N'.val + ascii(''A'')) + '
end

if @values_counter < @elements_to_select - 1
begin
set @n_joins = @n_joins + N' inner join ' + char(13) + N' comb as comb' + cast((@values_counter + 1) as nvarchar(16)) 
+ N' on ' + char(13) + ' comb' + @n_counter + '.val < comb' + cast((@values_counter + 1) as nvarchar(16)) + '.val '
end

set @values_counter = @values_counter + 1
end

set @n_unions = substring(@n_unions, 1, len(@n_unions) - 6)

set @n_glued_value = substring(@n_glued_value, 1, len(@n_glued_value) - 2)

set @n_glued_ascii_value = substring(@n_glued_ascii_value, 1, len(@n_glued_ascii_value) - 2)

------------------------------------------------------------------------------------
-- assemble the main query

declare @n_cmd nvarchar(max)

set @n_cmd = N'with comb as (' + char(13) + @n_unions + char(13) + N')' + char(13) + N'select ' + @n_select_list 

set @n_cmd = @n_cmd + @n_glued_value + N'as res_glued, ' + char(13) + @n_glued_ascii_value + N'res_text ' + char(13)

set @n_cmd = @n_cmd + 'from ' + char(13) + ' comb as comb0 ' + @n_joins + char(13) + N'order by res_text'

print @n_cmd

exec sp_executesql @n_cmd
end
go

-- example:

exec dbo.proc_generate_combinations 16, 8

Read 328 times
(1 in last 30 days)

Rate

3.67 (3)

You rated this post out of 5. Change rating

Share

Share

Rate

3.67 (3)

You rated this post out of 5. Change rating