Technical Article

Generating permutations - procedure

,

This procedure prepares a query for generating permutations of n-numbers set and executes it.

/***************************************************************************************************************
*
* Author Rafal Skotak
* Purpose This procedure generates permutations of the set of digits of the specified size
* Date 2008-02-04
*
***************************************************************************************************************/
if exists(select * from sys.objects where object_id = object_id('dbo.proc_permutations') and type = 'P')
drop procedure dbo.proc_permutations
go

create procedure dbo.proc_permutations
@elements int
as
begin
set nocount on

if @elements is null
begin
raiserror('Elements parameter is null', 16, 1)
return
end

if @elements < 2 or @elements > 9
begin
raiserror('Invalid parameter value (acceptable valueas are in the range 2-9)', 16, 1)
return
end

declare @counter int

set @counter = 0

declare @res_def nvarchar(max)
declare @select_res nvarchar(max)
declare @select_text nvarchar(max)
declare @select_glued nvarchar(max)
declare @num nvarchar(64)
declare @from_clause nvarchar(max)
declare @join_condition nvarchar(max)
declare @join_part nvarchar(max)
declare @previous_join_part nvarchar(max)

set @num = ''
set @res_def = ''
set @select_res = ''
set @select_text = ''
set @select_glued = ''
set @from_clause = ''
set @join_condition = ''
set @join_part = ''
set @previous_join_part = ''

while @counter < @elements
begin

set @num = cast(@counter as nvarchar(64))

----------------------------------------------------------------------------------------------------
-- prepare SELECT parts

if @counter > 0
set @res_def = @res_def + ' union ' + char(13)

set @res_def = @res_def + ' select ' + @num + ' as numb '
set @select_res = @select_res + ' res' + @num + '.numb,' + char(13)    
set @select_glued = @select_glued + ' cast(res' + @num + '.numb as varchar(64)) '

if @counter < @elements - 1
set @select_glued = @select_glued + ' + ' + char(13)
else
set @select_glued = @select_glued + ' as res_glued,' + char(13)

set @select_text = @select_text + ' char(res' + @num +'.numb + ascii(''A''))'

if @counter < @elements - 1
set @select_text = @select_text + ' + ' + char(13)
else
set @select_text = @select_text + ' as res_text' + char(13)

-----------------------------------------------------------------------------------------------------
-- prepare FROM parts

if @counter > 0
begin
set @join_part = 'res' + @num + '.numb <> res'

if @previous_join_part <> ''
set @join_condition = replace(@join_condition, @previous_join_part, @join_part)

set @previous_join_part = @join_part

if @join_condition <> ''
set @join_condition = @join_condition + ' and ' + char(13)

set @join_condition = @join_condition + ' ' + @join_part + cast((@counter - 1) as nvarchar(64)) + '.numb'

set @from_clause = @from_clause + ' inner join' + char(13) + ' res as res' + @num + ' on ' + char(13) + @join_condition
end
else
set @from_clause = ' res as res' + @num 

set @counter = @counter + 1
end

declare @n_cmd nvarchar(max)

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

set @n_cmd = 'with' + char(13) + ' res(numb)' + char(13) + 'as' + char(13) + '(' + char(13)
set @n_cmd = @n_cmd + @res_def + char(13) + ')' + char(13)
set @n_cmd = @n_cmd + 'select' + char(13) + @select_res + char(13) + @select_glued + char(13) + @select_text + char(13)
set @n_cmd = @n_cmd + 'from' + char(13) + @from_clause + char(13) + 'order by' + char(13) + ' res_glued'

print @n_cmd

exec (@n_cmd)
end
go

-- example:
dbo.proc_permutations 9

Rate

5 (1)

You rated this post out of 5. Change rating

Share

Share

Rate

5 (1)

You rated this post out of 5. Change rating