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

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